~choreonoid/choreonoid/debian

« back to all changes in this revision

Viewing changes to src/Base/LazyCaller.cpp

  • Committer: Thomas Moulard
  • Date: 2012-10-23 12:43:24 UTC
  • Revision ID: git-v1:351cf736ad49bc7a9a7b9767dee760a013517a5d
Tags: upstream/1.1.0
ImportedĀ UpstreamĀ versionĀ 1.1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
   @author Shin'ichiro Nakaoka
 
3
*/
 
4
 
 
5
#include "LazyCaller.h"
 
6
#include <QObject>
 
7
#include <QEvent>
 
8
#include <QCoreApplication>
 
9
#include <QThread>
 
10
#include <QSemaphore>
 
11
#include <boost/bind.hpp>
 
12
 
 
13
using namespace cnoid;
 
14
 
 
15
namespace {
 
16
 
 
17
    class CallEvent : public QEvent
 
18
    {
 
19
    public:
 
20
        CallEvent(const boost::function<void(void)>& function)
 
21
            : QEvent(QEvent::User),
 
22
              function(function) {
 
23
        }
 
24
        boost::function<void(void)> function;
 
25
    };
 
26
 
 
27
    class SynchronousCallEvent : public QEvent
 
28
    {
 
29
    public:
 
30
        SynchronousCallEvent(const boost::function<void(void)>& function, QSemaphore& semaphore)
 
31
            : QEvent(QEvent::User),
 
32
              function(function),
 
33
              semaphore(semaphore) {
 
34
        }
 
35
        boost::function<void(void)> function;
 
36
        QSemaphore& semaphore;
 
37
    };
 
38
    
 
39
    class CallEventHandler : public QObject
 
40
    {
 
41
      public:
 
42
        CallEventHandler() {
 
43
            mainThreadId = QThread::currentThreadId();
 
44
        }
 
45
        virtual bool event(QEvent* e);
 
46
        Qt::HANDLE mainThreadId;
 
47
    };
 
48
    
 
49
    CallEventHandler callEventHandler;
 
50
}
 
51
 
 
52
 
 
53
void cnoid::callLater(const boost::function<void(void)>& function, int priority)
 
54
{
 
55
    QCoreApplication::postEvent(&callEventHandler, new CallEvent(function), priority);
 
56
}
 
57
 
 
58
 
 
59
void cnoid::callSynchronously(const boost::function<void(void)>& function, int priority)
 
60
{
 
61
    if(QThread::currentThreadId() == callEventHandler.mainThreadId){
 
62
        callLater(function, priority);
 
63
    } else {
 
64
        QSemaphore semaphore;
 
65
        QCoreApplication::postEvent(&callEventHandler, new SynchronousCallEvent(function, semaphore), priority);
 
66
        semaphore.acquire(); // wait for finish
 
67
    }
 
68
}
 
69
 
 
70
 
 
71
bool CallEventHandler::event(QEvent* e)
 
72
{
 
73
    CallEvent* callEvent = dynamic_cast<CallEvent*>(e);
 
74
    if(callEvent){
 
75
        callEvent->function();
 
76
        return true;
 
77
    } else {
 
78
        SynchronousCallEvent* scEvent = dynamic_cast<SynchronousCallEvent*>(e);
 
79
        if(scEvent){
 
80
            scEvent->function();
 
81
            scEvent->semaphore.release(); // wake up
 
82
            return true;
 
83
        }
 
84
    }
 
85
    return false;
 
86
}
 
87
 
 
88
 
 
89
LazyCaller::LazyCaller()
 
90
{
 
91
    isCallEventPending = false;
 
92
    priority = IDLE_PRIORITY_HIGH;
 
93
}
 
94
 
 
95
 
 
96
LazyCaller::LazyCaller(const boost::function<void(void)>& function, int priority)
 
97
    : function(function),
 
98
      priority(priority)
 
99
{
 
100
    isCallEventPending = false;
 
101
}
 
102
 
 
103
 
 
104
void LazyCaller::set(const boost::function<void(void)>& function, int priority)
 
105
{
 
106
    this->function = function;
 
107
    this->priority = priority;
 
108
}
 
109
 
 
110
 
 
111
void LazyCaller::setPriority(int priority)
 
112
{
 
113
    this->priority = priority;
 
114
}
 
115
        
 
116
 
 
117
void LazyCaller::request()
 
118
{
 
119
    if(!isCallEventPending){
 
120
        isCallEventPending = true;
 
121
        callLater(boost::bind(&LazyCaller::onRequest, this), priority);
 
122
    }
 
123
}
 
124
 
 
125
 
 
126
void LazyCaller::onRequest()
 
127
{
 
128
    isCallEventPending = false;
 
129
    function();
 
130
}