aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Foundation/include/Poco/Activity.h
blob: a7297f144f476078c7bceb47f736c293696dbd38 (plain) (blame)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//
// Activity.h
//
// Library: Foundation
// Package: Threading
// Module:  ActiveObjects
//
// Definition of the Activity template class.
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:	BSL-1.0
//


#ifndef Foundation_Activity_INCLUDED
#define Foundation_Activity_INCLUDED


#include "Poco/Foundation.h"
#include "Poco/RunnableAdapter.h"
#include "Poco/ThreadPool.h"
#include "Poco/Event.h"
#include "Poco/Mutex.h"


namespace Poco {


template <class C>
class Activity: public Runnable
	/// This template class helps to implement active objects.
	/// An active object uses threads to decouple method
	/// execution from method invocation, or to perform tasks
	/// autonomously, without intervention of a caller.
	///
	/// An activity is a (typically longer running) method
	/// that executes within its own task. Activities can
	/// be started automatically (upon object construction)
	/// or manually at a later time. Activities can also
	/// be stopped at any time. However, to make stopping
	/// an activity work, the method implementing the
	/// activity has to check periodically whether it
	/// has been requested to stop, and if so, return. 
	/// Activities are stopped before the object they belong to is
	/// destroyed. Methods implementing activities cannot have arguments
	/// or return values. 
	///
	/// Activity objects are used as follows:
	///
	///     class ActiveObject
	///     {
	///     public:
	///         ActiveObject(): 
	///             _activity(this, &ActiveObject::runActivity)
	///         {
	///             ...
	///         }
	///   
	///         ...
	///  
	///     protected:
	///         void runActivity()
	///         {
	///             while (!_activity.isStopped())
	///             {
	///                 ...
	///             }
	///         }
	///
	///     private:
	///         Activity<ActiveObject> _activity;
	///     };
{
public:
	typedef RunnableAdapter<C> RunnableAdapterType;
	typedef typename RunnableAdapterType::Callback Callback;

	Activity(C* pOwner, Callback method):
		_pOwner(pOwner),
		_runnable(*pOwner, method),
		_stopped(true),
		_running(false),
		_done(false)
		/// Creates the activity. Call start() to
		/// start it.
	{
		poco_check_ptr (pOwner);
	}
	
	~Activity()
		/// Stops and destroys the activity.
	{
		try
		{
			stop();
			wait();
		}
		catch (...)
		{
			poco_unexpected();
		}
	}
	
	void start()
		/// Starts the activity by acquiring a
		/// thread for it from the default thread pool.
	{
		start(ThreadPool::defaultPool());
	}

	void start(ThreadPool& pool)
	{
		FastMutex::ScopedLock lock(_mutex);
		
		if (!_running)
		{
			_done.reset();
			_stopped = false;
			_running = true;
			try
			{
				pool.start(*this);
			}
			catch (...)
			{
				_running = false;
				throw;
			}
		}
	}
	
	void stop()
		/// Requests to stop the activity.
	{
		FastMutex::ScopedLock lock(_mutex);

		_stopped = true;
	}
	
	void wait()
		/// Waits for the activity to complete.
	{
		if (_running)
		{
			_done.wait();
		}
	}

	void wait(long milliseconds)
		/// Waits the given interval for the activity to complete.
		/// An TimeoutException is thrown if the activity does not
		/// complete within the given interval.
	{
		if (_running)
		{
			_done.wait(milliseconds);
		}
	}
	
	bool isStopped() const
		/// Returns true if the activity has been requested to stop.
	{
		return _stopped;
	}
	
	bool isRunning() const
		/// Returns true if the activity is running.
	{
		return _running;
	}

protected:
	void run()
	{
		try
		{
			_runnable.run();
		}
		catch (...)
		{
			_running = false;
			_done.set();
			throw;
		}
		_running = false;
		_done.set();
	}
	
private:
	Activity();
	Activity(const Activity&);
	Activity& operator = (const Activity&);

	C*                  _pOwner;
	RunnableAdapterType _runnable;
	volatile bool       _stopped;
	volatile bool       _running;
	Event               _done;
	FastMutex           _mutex;
};


} // namespace Poco


#endif // Foundation_Activity_INCLUDED