File: fluid.c

package info (click to toggle)
rscheme 0.7.2-1.1
  • links: PTS
  • area: main
  • in suites: slink
  • size: 10,672 kB
  • ctags: 12,430
  • sloc: lisp: 37,104; ansic: 29,763; cpp: 2,630; sh: 1,677; makefile: 568; yacc: 202; lex: 175; perl: 33
file content (134 lines) | stat: -rw-r--r-- 3,563 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*-----------------------------------------------------------------*-C-*---
 * File:    handc/runtime/fluid.c
 *
 *          Copyright (C)1997 Donovan Kolbly <d.kolbly@rscheme.org>
 *          as part of the RScheme project, licensed for free use.
 *          See <http://www.rscheme.org/> for the latest information.
 *
 * File version:     1.3
 * File mod date:    1997.11.29 23:10:50
 * System build:     v0.7.2, 97.12.21
 *
 *------------------------------------------------------------------------*/

#include <rscheme/scheme.h>
#include <rscheme/smemory.h>
#include <rscheme/allocns.h>

/* support for fluid variables 
   (this style of fluid variable is deprecated in 0.9, but we
   need some context-switch performance improvement in the meantime...)
 */

/* winding a fluid TL contour;
   store TL bindings in `saved' values
   and load `inside' values into TL bindings
*/

#define FTLC_BINDINGS        SLOT(0)
#define FTLC_INSIDE_VALUES   SLOT(1)
#define FTLC_SAVED_VALUES    SLOT(2)

static void shift_tl_values( obj var_vec, obj save_into, obj load_from )
{
  UINT_32 i, sz;
  obj tlv;

  sz = SIZEOF_PTR(var_vec);
  for (i=0; i<sz; i+=SLOT(1))
    {
      tlv = gvec_ref( var_vec, i );
#if 0
      fprintf( stdout, "updating %s ", symbol_text( gvec_ref(tlv,SLOT(0)) ) );
      fprinto( stdout, gvec_ref(tlv,SLOT(1)) );
      fprintf( stdout, " ==> " );
      fprinto( stdout, gvec_ref(load_from,i) );
      fprintf( stdout, "\n" );
#endif
      gvec_write( save_into, i, gvec_ref(tlv,SLOT(1)) );
      gvec_write( tlv, SLOT(1), gvec_ref(load_from,i) );
    }
}

void wind_fluid_tl_contour( obj ftlc )
{
  shift_tl_values( gvec_ref( ftlc, FTLC_BINDINGS ),
		   gvec_ref( ftlc, FTLC_SAVED_VALUES ),
		   gvec_ref( ftlc, FTLC_INSIDE_VALUES ) );
}

void unwind_fluid_tl_contour( obj ftlc )
{
  shift_tl_values( gvec_ref( ftlc, FTLC_BINDINGS ),
		   gvec_ref( ftlc, FTLC_INSIDE_VALUES ),
		   gvec_ref( ftlc, FTLC_SAVED_VALUES ) );
}

/* returns an "ancestor descriptor", which is a vector
 * whose first element is the common cell and whose remaining
 * elements are the car's of the chain from the common cell
 * to the `to' cell (not including the common cell).
 *
 *  this technique costs an allocation at context switch time,
 *  but is MUCH easier than avoiding the mass of continuations
 *  that would be allocated in the rewinder
 */

obj find_common_ancestor( obj from, obj to )
{
  obj f, t, v, k;
  unsigned n;

  if (EQ(from,to))
    return make1( vector_class, from );

  /* this is not MP safe! */

  /* mark the cells in the `from' list */

  for (f=from; PAIR_P(f); f=pair_cdr(f))
    {
      PTR_TO_HDRPTR(f)->pob_size += 1;
    }

  /* crawl up the `to' list looking for something with the bit set */

  n = SLOT(1);
  for (t=to; PAIR_P(t); t=pair_cdr(t))
    {
      if (PTR_TO_HDRPTR(t)->pob_size & 1)
	break;
      if (!VECTOR_P(pair_car(t)))
	n += SLOT(1);
    }

/* found a common ancestor or ran out of `to' list; 
 * in either case, `n' is the number of slots we need
 * in the ancestor vector (initially one for the common
 * cell, and incremented once for each value we'll put
 * in it)
 */

 /*
  * remove the marks from the `from' list...
  */
  for (f=from; PAIR_P(f); f=pair_cdr(f))
    {
      PTR_TO_HDRPTR(f)->pob_size -= 1;
    }

  /* construct the ancestor descriptor */
  
  v = alloc( n, vector_class );
  gvec_write_init( v, SLOT(0), t );
  
  for (n=SLOT(1), k=to; !EQ(k,t); k=pair_cdr(k))
    {
      if (!VECTOR_P(pair_car(k)))
	{
	  gvec_write_init( v, n, pair_car(k) );
	  n += SLOT(1);
	}
    }
  return v;
}