aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext/tutorial/thread2/main.cpp
blob: ce2a170e69f581cf47c691d9ac99a1be41c6254d (plain)
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
/* 
flext tutorial - threads 2 

Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
For information on usage and redistribution, and for a DISCLAIMER OF ALL
WARRANTIES, see the file, "license.txt," in this distribution.  

-------------------------------------------------------------------------

This shows an example of multiple threads and syncing with a thread conditional
*/

// define FLEXT_THREADS for thread usage. Flext must also have been compiled with that defined!
#ifndef FLEXT_THREADS
#define FLEXT_THREADS
#endif

#include <flext.h>

#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 301)
#error You need at least flext version 0.3.1
#endif


class thread2:
	public flext_base
{
	FLEXT_HEADER(thread2,flext_base)
 
public:
	thread2(int del); 

protected:
	void m_start(int st);
	void m_stop();
	void m_text();

	void m_textout();

private:
	FLEXT_THREAD_I(m_start); // define threaded callback for method m_start
	FLEXT_CALLBACK(m_stop);  // normal callback for m_stop
	FLEXT_CALLBACK(m_text);  // turn on console output

	FLEXT_THREAD(m_textout); // text output

	float delay;
	volatile int count;

	// caution: CodeWarrior seems to ignore volatile modifier!!
	volatile bool stopit,running,blipping;  // flags for running and stopping

	// thread conditional for stop signal
	ThrCond cond;
};

FLEXT_NEW_1("thread2",thread2,int)



thread2::thread2(int del):
	delay(del/1000.f),
	stopit(false),
	running(false),blipping(false)
{ 
	AddInAnything();  
	AddOutInt(2); 
	SetupInOut();  // set up inlets and outlets

	FLEXT_ADDMETHOD(0,m_start); // register start for integer numbers (floats in PD)
	FLEXT_ADDMETHOD_(0,"text",m_text); // register m_text method for "text" tag
	FLEXT_ADDMETHOD_(0,"stop",m_stop); // register m_text method for "stop" tag
} 

void thread2::m_start(int st)
{
	// if already running, just set back the counter
	if(running) { count = st; return; }

	running = true;

	// loop until either the system exit flag or the "stopit" flag is set 
	for(count = st; !ShouldExit() && !stopit; ++count) 
	{
		Sleep(delay);
		ToOutInt(0,count); // output loop count
	}

	cond.Lock(); // lock conditional
	running = false; // change state flag
	cond.Signal(); // signal changed flag to watiting "stop" method
	cond.Unlock(); // unlock conditional
}

void thread2::m_stop()
{
	cond.Lock(); // lock conditional
	stopit = true; // set termination flag

	while(*(&running) || *(&blipping)) // workaround for CodeWarrior!
	{
		cond.Wait(); // wait for signal by running threads
	}

	// --- Here, the threads should have stopped ---

	stopit = false; // reset flag
	cond.Unlock(); // unlock conditional
}


void thread2::m_text()
{
	FLEXT_CALLMETHOD(m_textout);
}

void thread2::m_textout()
{
	if(blipping) return;
	blipping = true;

	while(!ShouldExit() && !stopit) {
		post("%i",count);
		Sleep(1.f);
	}

	cond.Lock(); // lock conditional
	blipping = false; // change state flag
	cond.Signal(); // signal changed flag to watiting "stop" method
	cond.Unlock(); // unlock conditional
}