File: conttest.cc

package info (click to toggle)
wvstreams 4.6.1-1
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 6,820 kB
  • ctags: 7,837
  • sloc: cpp: 64,203; ansic: 4,154; sh: 4,094; makefile: 549; perl: 402
file content (123 lines) | stat: -rw-r--r-- 3,447 bytes parent folder | download | duplicates (8)
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
/*
 * A test program for WvCont (continuable callbacks).
 */
#include "wvcont.h"
#include <stdio.h>


static void *nonfunc(void *_x)
{
    long x = (long)_x;
    
    return (void *)(1234560000 + x);
}


static void *func(void *_x)
{
    long x = (long)_x;
    
    for (int count = 0; count < 4 && WvCont::isok(); count++)
	WvCont::yield((void *)++x);
    return (void *) -(++x);
}


class Honk
{
public:
    const char *id;
    
    WvContCallback cb;
    
    Honk(const char *_id)
        { id = _id; }
    
    void honk_at(Honk &a)
    {
	cb = WvCont(wv::bind(&Honk::honker, this, a, _1));
    }

private:
    void *honker(Honk &h, void *_x)
    {
	long x = (long)_x;
	printf("%s: STARTING (%ld)\n", id, x);
	
	for (x--; WvCont::isok() && x > 0; x--)
	{
	    printf("%s: --> Honking in (%ld)\n", id, x);
	    h.cb((void *)x);
	    printf("%s: <-- Honking out (%ld)\n", id, x);
	}
	
	printf("%s: DONE\n", id);
	return (void *)x;
    }
};


int main()
{
    typedef wv::function<void*(void*)> CbType;
    
    // basic functionality (including nested tasks)
    {
	CbType cbx = func; // not runnable itself: no yield allowed
	CbType cb1 = WvCont(cbx); // a subtask
	CbType cb2 = WvCont(cb1); // another subtask on top
	CbType cb3 = cb2; // a copy of the second subtask
	// note that in the above, there's really only one context in which
	// 'func' actually gets called; there are no parallel running 'func's.
	// cb2's task calls into cb1's task, however.
    
	printf("zot1: %ld\n", (long)cb1((void *)100));
	printf("zot1: %ld\n", (long)cb2((void *)200));
	printf("zot1: %ld\n", (long)cb3((void *)300));
	cb1 = WvCont(nonfunc);
	printf("zot2: %ld\n", (long)cb1((void *)400));
	printf("zot2: %ld\n", (long)cb2((void *)500));
	printf("zot2: %ld\n", (long)cb3((void *)600));
	cb2 = nonfunc;
	printf("zot3: %ld\n", (long)cb1((void *)700));
	printf("zot3: %ld\n", (long)cb2((void *)800));
	printf("zot3: %ld\n", (long)cb3((void *)900));
	cb3 = nonfunc;
	printf("zot4: %ld\n", (long)cb1((void *)1000));
	printf("zot4: %ld\n", (long)cb2((void *)1100));
	printf("zot4: %ld\n", (long)cb3((void *)1200));
    }
    
    // fun with recursive continuations.  If this doesn't do something
    // predictable, we'll get screwy bugs when we use this in WvStreams - just
    // like we did with the pre-WvCont continue_select() implementation.
    // 
    // The *desired* behaviour here is the same as with real recursive
    // function calls: if a calls b who calls c, and then c calls a again,
    // then a should do its thing, return (or yield), then c will finish,
    // yield, then b will finish, yield, and then a will have a chance to run
    // again.
    // 
    // In old wvstreams, we would silently short-circuit the recursion (the
    // inner a would yield immediately without doing anything).  This is
    // easy to implement, but causes problems if c actually expects a to do
    // something.
    // 
    // Unfortunately, the semantics of this are tricky with continuations:
    // when we call the inner a, we re-enter its context, but that context
    // is waiting for b to return.  It can't do anything unless b returns,
    // so what can we do?
    // 
    // ...we assert() instead.  So expect an assertion failure below.
    printf("Expect an assertion failure shortly!\n");
    {
	Honk h1("honk1"), h2("honk2"), h3("honk3");
	h1.honk_at(h2);
	h2.honk_at(h3);
	h3.honk_at(h1);
	
	h1.cb((void *)5);
    }
    
    return 0;
}