home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / microcode / futures.h < prev    next >
C/C++ Source or Header  |  1999-01-02  |  7KB  |  214 lines

  1. /* -*-C-*-
  2.  
  3. $Id: futures.h,v 9.29 1999/01/02 06:11:34 cph Exp $
  4.  
  5. Copyright (c) 1987, 1988, 1989, 1990, 1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. /* This file contains macros useful for dealing with futures */
  23.  
  24. /* NOTES ON FUTURES, derived from the rest of the interpreter code
  25.  
  26.    ASSUMPTION: The syntaxer is hereby assumed NEVER to generate primitive
  27.    combinations unless the primitive itself is output in the code stream.
  28.    Therefore, we don't have to explicitly check here that the expression
  29.    register has a primitive in it.
  30.  
  31.    ASSUMPTION: The SYMBOL slot of a VARIABLE does NOT contain a future, nor
  32.    do the cached lexical address slots.
  33.  
  34.    ASSUMPTION: Environment structure, which is created only by the
  35.    interpreter, never contains FUTUREs on its spine.
  36.  
  37.    ASSUMPTION: History objects are never created using futures.
  38.  
  39.    ASSUMPTION: State points, which are created only by the interpreter,
  40.    never contain FUTUREs except possibly as the thunks (which are handled
  41.    by the apply code).
  42.  
  43.    OPTIMIZATIONS (?):
  44.    After a lot of discussion, we decided that variable reference will check
  45.    whether a value stored in the environment is a determined future which
  46.    is marked spliceable.  If so, it will splice out the future from the
  47.    environment slot to speed up subsequent references.
  48.  
  49.    EQ? does a normal identity check and only if this fails does it touch the
  50.    arguments.  The same thing does not speed up MEMQ or ASSQ in the normal
  51.    case, so it is omitted there.
  52.  
  53.    The following are NOT done, but might be useful later
  54.    (1) Splicing on SET! operations
  55.    (2) Splicing at apply and/or primitive apply
  56.    (3) Splicing all arguments when a primitive errors on any of them
  57.    (4) Splicing within the Arg_n_Type macro rather than after longjmping
  58.        to the error handler.
  59.  
  60.    KNOWN PROBLEMS:
  61.    (1) Garbage collector should be modified to splice out futures.  DONE.
  62.  
  63.    (2) Purify should be looked at and we should decide what to do about
  64.        purifying an object with a reference to a future (it should probably
  65.        become constant but not pure).
  66.  
  67.    (3) Look at Impurify and Side-Effect-Impurify to see if futures
  68.        affect them in any way. */
  69.  
  70. /* Data structure definition */
  71.  
  72. /* The IS_DETERMINED slot has one of the following type of values:
  73.     #F    if the value is not yet known;
  74.     #T    if the value is known and the garbage collector is free
  75.       to remove the future object in favor of its value everywhere;
  76.    else    the value is known, but the GC must leave the future object. */
  77.  
  78. #define FUTURE_VECTOR_HEADER    0
  79. #define FUTURE_IS_DETERMINED    1
  80. #define FUTURE_LOCK             2
  81. #define FUTURE_VALUE        3    /* if known, else */
  82. #define FUTURE_QUEUE        3    /* tasks waiting for value */
  83. #define FUTURE_PROCESS        4
  84. #define FUTURE_STATUS        5
  85. #define FUTURE_ORIG_CODE    6
  86. #define FUTURE_PRIVATE        7
  87. #define FUTURE_WAITING_ON    8
  88. #define FUTURE_METERING        9
  89. #define FUTURE_USER        10
  90.  
  91. #define Future_Is_Locked(P)                        \
  92.   ((MEMORY_REF ((P), FUTURE_LOCK)) != SHARP_F)
  93.  
  94. #define Future_Has_Value(P)                        \
  95.   ((MEMORY_REF ((P), FUTURE_IS_DETERMINED)) != SHARP_F)
  96.  
  97. #define Future_Value(P)                            \
  98.   (MEMORY_REF ((P), FUTURE_VALUE))
  99.  
  100. #define Future_Spliceable(P)                        \
  101.   (((MEMORY_REF ((P), FUTURE_IS_DETERMINED)) == SHARP_T) &&        \
  102.    ((MEMORY_REF ((P), FUTURE_LOCK)) == SHARP_F))
  103.  
  104. #define Future_Is_Keep_Slot(P)                        \
  105.   (! (BOOLEAN_P (MEMORY_REF ((P), FUTURE_IS_DETERMINED))))
  106.  
  107. #ifndef COMPILE_FUTURES
  108.  
  109. #define TOUCH_IN_PRIMITIVE(P, To_Where) To_Where = (P)
  110. #define TOUCH_SETUP(object) Microcode_Termination (TERM_TOUCH)
  111. #define Log_Touch_Of_Future(F) {}
  112. #define Call_Future_Logging()
  113. #define Must_Report_References() (false)
  114. #define FUTURE_VARIABLE_SPLICE(P, Offset, Value)
  115.  
  116. #else /* COMPILE_FUTURES */
  117.  
  118. /* TOUCH_IN_PRIMITIVE is used by primitives which are not
  119.    strict in an argument but which touch it none the less. */
  120.  
  121. #define TOUCH_IN_PRIMITIVE(P, To_Where)                    \
  122. {                                    \
  123.   SCHEME_OBJECT Value = (P);                        \
  124.   while (FUTURE_P (Value))                        \
  125.     {                                    \
  126.       if (Future_Has_Value (Value))                    \
  127.     {                                \
  128.       if (Future_Is_Keep_Slot (Value))                \
  129.         {                                \
  130.           Log_Touch_Of_Future (Value);                \
  131.         }                                \
  132.       Value = (Future_Value (Value));                \
  133.     }                                \
  134.       else                                \
  135.     {                                \
  136.       Val = Value;                            \
  137.       PRIMITIVE_ABORT (PRIM_TOUCH);                    \
  138.     }                                \
  139.     }                                    \
  140.   (To_Where) = Value;                            \
  141. }
  142.  
  143. #define TOUCH_SETUP(object)                        \
  144. {                                    \
  145.   Save_Cont ();                                \
  146.  Will_Push (STACK_ENV_EXTRA_SLOTS + 2);                    \
  147.   STACK_PUSH (object);                            \
  148.   STACK_PUSH (Get_Fixed_Obj_Slot (System_Scheduler));            \
  149.   STACK_PUSH (STACK_FRAME_HEADER + 1);                    \
  150.  Pushed ();                                \
  151. }
  152.  
  153. #define FUTURE_VARIABLE_SPLICE(P, Offset, Value)            \
  154. {                                    \
  155.   while ((FUTURE_P (Value)) && (Future_Spliceable (Value)))        \
  156.     {                                    \
  157.       Value = (Future_Value (Value));                    \
  158.       MEMORY_SET (P, Offset, Value);                    \
  159.     }                                    \
  160. }
  161.  
  162. #ifdef FUTURE_LOGGING
  163.  
  164. #define Touched_Futures_Vector() (Get_Fixed_Obj_Slot (Touched_Futures))
  165.  
  166. #define Logging_On()                            \
  167.   ((Valid_Fixed_Obj_Vector ()) && (Touched_Futures_Vector ()))
  168.  
  169. /* Log_Touch_Of_Future adds the future which was touched to the vector
  170.    of touched futures about which the scheme portion of the system has
  171.    not yet been informed. */
  172.  
  173. #define Log_Touch_Of_Future(F)                        \
  174. {                                    \
  175.   if (Logging_On ())                            \
  176.     {                                    \
  177.       SCHEME_OBJECT TFV = (Touched_Futures_Vector ());            \
  178.       long Count =                            \
  179.     ((UNSIGNED_FIXNUM_TO_LONG (VECTOR_REF (TFV, 0))) + 1);        \
  180.       (VECTOR_REF (TFV, 0)) = (LONG_TO_UNSIGNED_FIXNUM (Count));    \
  181.       if (Count < (VECTOR_LENGTH (TFV)))                \
  182.     (VECTOR_REF (TFV, Count)) = (OBJECT_NEW_TYPE (TC_VECTOR, F));    \
  183.     }                                    \
  184. }
  185.  
  186. /* Call_Future_Logging calls a user defined scheme routine if the vector
  187.    of touched futures has a nonzero length. */
  188.  
  189. #define Must_Report_References()                    \
  190.   ((Logging_On ()) &&                            \
  191.    ((UNSIGNED_FIXNUM_TO_LONG                        \
  192.      (VECTOR_REF ((Touched_Futures_Vector ()), 0)))            \
  193.     > 0))
  194.  
  195. #define Call_Future_Logging()                        \
  196. {                                    \
  197.  Will_Push (STACK_ENV_EXTRA_SLOTS + 2);                    \
  198.   STACK_PUSH (Touched_Futures_Vector ());                \
  199.   STACK_PUSH (Get_Fixed_Obj_Slot (Future_Logger));            \
  200.   STACK_PUSH (STACK_FRAME_HEADER + 1);                    \
  201.  Pushed ();                                \
  202.   (Touched_Futures_Vector ()) = SHARP_F;                \
  203.   goto Apply_Non_Trapping;                        \
  204. }
  205.  
  206. #else /* not FUTURE_LOGGING */
  207.  
  208. #define Log_Touch_Of_Future(F) {}
  209. #define Call_Future_Logging()
  210. #define Must_Report_References() (false)
  211.  
  212. #endif /* FUTURE_LOGGING */
  213. #endif /* COMPILE_FUTURES */
  214.