Poco是一个强大的,用于构建C++程序的类库,它提供了许多非常好用的部件来帮助我们更快的开发C++应用程序,异步执行的相关部件正是这些好用的部件中的一部分。这里我们来看一下Poco库的异步执行组件的实现。
Poco库的异步执行组件主要有TaskManager,Task,ThreadPool等等。这里就主要从这些组件着手进行分析。
TaskManager/Task的使用
首先来看一下TaskManager/Task的使用。
1. 要使用Poco库的TaskManager来帮我们管理异步执行的任务,我们首先需要创建一个类,也是我们的任务的抽象,继承Poco的Task类,override其中的virtual函数virtual void runTask(),并在runTask()的实现中包含我们希望去异步执行的代码。
2. 然后创建一个线程池对象ThreadPool。这一步可选。
3. 创建一个TaskManager类的对象,并将前一步创建的线程池对象传给TaskManager的构造函数。TaskManager管理的所有Task都将在这个线程池的线程中执行。如果没有为TaskManager创建单独的线程池,则所有Task都将在default的线程池中执行。
4. 创建一个Task的对象。这个Task对象应该通过operator new,在堆上创建。
5. 通过前面创建的TaskManager对象,启动执行创建的Task。在Task执行完之后,TaskManager自己会把Task对象给delete掉。
具体还是来看一下代码比较方便:
#include <iostream>
#include <Poco/TaskManager.h>
#include <Poco/Task.h>
#include <Poco/TaskNotification.h>
#include <Poco/Thread.h>
#include <Poco/ThreadPool.h>
using namespace Poco;
using namespace std;
class DemoTask : public Task {
public:
DemoTask();
virtual ~DemoTask();
virtual void runTask();
};
DemoTask::DemoTask()
: Task("DemoTask") {
}
DemoTask::~DemoTask() {
}
void DemoTask::runTask() {
Thread::sleep(3000);
cout << "DemoTask runtask." << endl;
}
int main() {
ThreadPool threadPool(2, 32);
TaskManager taskManager(threadPool);
DemoTask * demoTask = new DemoTask;
taskManager.start(demoTask);
taskManager.joinAll();
cout << "Demo run end." << endl;
return 0;
}
这就是使用TaskManager/Task执行异步任务的基本方法了。但TaskManager提供的功能却不只如此,它还可以在Task的状态发生改变时,通过Observer通知我们具体的用法如下:
class TaskObserver {
public:
TaskObserver();
void handleTaskFinished(TaskStartedNotification *startedNotify);
void handleTaskCancelled(TaskCancelledNotification *cancelledNotify);
void handleTaskFinished(TaskFinishedNotification *completedNotify);
void handleTaskFailed(TaskFailedNotification *failedNotify);
void handleTaskProgressUpdated(TaskProgressNotification *progressNotify);
};
TaskObserver::TaskObserver() {
}
void TaskObserver::handleTaskFinished(TaskStartedNotification *startedNotify) {
startedNotify->release();
}
void TaskObserver::handleTaskCancelled(TaskCancelledNotification *cancelledNotify) {
cancelledNotify->release();
}
void TaskObserver::handleTaskFinished(TaskFinishedNotification *completedNotify) {
cout << "Task finished." << endl;
completedNotify->release();
}
void TaskObserver::handleTaskFailed(TaskFailedNotification *failedNotify) {
failedNotify->release();
}
void TaskObserver::handleTaskProgressUpdated(TaskProgressNotification *progressNotify) {
progressNotify->release();
}
int main() {
ThreadPool threadPool(2, 32);
TaskManager taskManager(threadPool);
TaskObserver observer;
Observer<TaskObserver, TaskFinishedNotification> finishedObserver(observer, &TaskObserver::handleTaskFinished);
taskManager.addObserver(finishedObserver);
DemoTask * demoTask = new DemoTask;
taskManager.start(demoTask);
在前面那个demo的基础之上,注册observer,并接收TaskManager关于task状态变化的通知。编译运行上面的这段程序,可以看到如下的输出:
DemoTask runtask.
Task finished.
Demo run end.
这里要注意,在收到Notification,处理了事件之后,要主动地release传进来的Notification,否则会发生内存泄漏。后面我们会通过对代码的分析来更详细的了解这样做的原因。
TaskManager的实现
来看TaskManager的实现,同时也再次全面的看一下TaskManager提供的功能即接口。TaskManager这个class的定义如下:
namespace Poco {
class Notification;
class ThreadPool;
class Exception;
class Foundation_API TaskManager
/// The TaskManager manages a collection of tasks
/// and monitors their lifetime.
///
/// A TaskManager has a built-in NotificationCenter that
/// is used to send out notifications on task progress
/// and task states. See the TaskNotification class and its
/// subclasses for the various events that result in a notification.
/// To keep the number of notifications small, a TaskProgressNotification
/// will only be sent out once in 100 milliseconds.
{
public:
typedef AutoPtr<Task> TaskPtr;
typedef std::list<TaskPtr> TaskList;
TaskManager();
/// Creates the TaskManager, using the
/// default ThreadPool.
TaskManager(ThreadPool& pool);
/// Creates the TaskManager, using the
/// given ThreadPool.
~TaskManager();
/// Destroys the TaskManager.
void start(Task* pTask);
/// Starts the given task in a thread obtained
/// from the thread pool.
///
/// The TaskManager takes ownership of the Task object
/// and deletes it when it it finished.
void cancelAll();
/// Requests cancellation of all tasks.
void joinAll();
/// Waits for the completion of all the threads
/// in the TaskManager's thread pool.
///
/// Note: joinAll() will wait for ALL tasks in the
/// TaskManager's ThreadPool to complete. If the
/// ThreadPool has threads created by other
/// facilities, these threads must also complete
/// before joinAll() can return.
TaskList taskList() const;
/// Returns a copy of the internal task list.
int count() const;
/// Returns the number of tasks in the internal task list.
void addObserver(const AbstractObserver& observer);
/// Registers an observer with the NotificationCenter.
/// Usage:
/// Observer<MyClass, MyNotification> obs(*this, &MyClass::handleNotification);
/// notificationCenter.addObserver(obs);
void removeObserver(const AbstractObserver& observer);
/// Unregisters an observer with the NotificationCenter.
static const int MIN_PROGRESS_NOTIFICATION_INTERVAL;
protected:
void postNotification(const Notification::Ptr& pNf);
/// Posts a notification to the task manager's
/// notification center.
void taskStarted(Task* pTask);
void taskProgress(Task* pTask, float progress);
void taskCancelled(Task* pTask);
void taskFinished(Task* pTask);
void taskFailed(Task* pTask, const Exception& exc);
private:
ThreadPool& _threadPool;
TaskList _taskList;
Timestamp _lastProgressNotification;
NotificationCenter _nc;
mutable FastMutex _mutex;
fr