~unity-api-team/unity-scopes-api/child-scopes-option

« back to all changes in this revision

Viewing changes to demo/scope-C.cpp

  • Committer: Michi Henning
  • Date: 2013-11-19 02:51:46 UTC
  • mto: This revision was merged to the branch mainline in revision 62.
  • Revision ID: michi.henning@canonical.com-20131119025146-kglcalpphl4ozzk7
Fixed scoperegistry to use new scoperunner and to figure out which scopes to run from config files.
Still to do:
- deal with overrides and OEM scopes, particularly the grouping aspect.
- SignalThread needs to invoke a callback for clean shut-down on receipt of SIGINT.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2013 Canonical Ltd
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify
5
 
 * it under the terms of the GNU General Public License version 3 as
6
 
 * published by the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful,
9
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 * GNU General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Authored by: Michi Henning <michi.henning@canonical.com>
17
 
 */
18
 
 
19
 
#include <scopes/ScopeBase.h>
20
 
#include <scopes/ResultItem.h>
21
 
#include <scopes/Category.h>
22
 
#include <scopes/Reply.h>
23
 
 
24
 
#include <algorithm>
25
 
#include <condition_variable>
26
 
#include <iostream>
27
 
#include <list>
28
 
#include <mutex>
29
 
#include <unistd.h>
30
 
 
31
 
#define EXPORT __attribute__ ((visibility ("default")))
32
 
 
33
 
using namespace std;
34
 
using namespace unity::api::scopes;
35
 
 
36
 
// Simple queue that stores query-string/reply pairs, using MyQuery* as a key for removal.
37
 
// The put() method adds a pair at the tail, and the get() method returns a pair at the head.
38
 
// get() suspends the caller until an item is available or until the queue is told to finish.
39
 
// get() returns true if it returns a pair, false if the queue was told to finish.
40
 
// remove() searches for the entry with the given key and erases it.
41
 
 
42
 
class MyQuery;
43
 
 
44
 
class Queue
45
 
{
46
 
public:
47
 
    void put(MyQuery const* query, string const& query_string, ReplyProxy const& reply_proxy)
48
 
    {
49
 
        std::lock_guard<std::mutex> lock(mutex_);
50
 
        queries_.push_back(QueryData { query, query_string, reply_proxy });
51
 
        condvar_.notify_one();
52
 
    }
53
 
 
54
 
    bool get(string& query_string, ReplyProxy& reply_proxy)
55
 
    {
56
 
        std::unique_lock<std::mutex> lock(mutex_);
57
 
        condvar_.wait(lock, [this] { return !queries_.empty() || done_; });
58
 
        if (done_)
59
 
        {
60
 
            condvar_.notify_all();
61
 
        }
62
 
        else
63
 
        {
64
 
            auto qd = queries_.front();
65
 
            queries_.pop_front();
66
 
            query_string = qd.query_string;
67
 
            reply_proxy = qd.reply_proxy;
68
 
        }
69
 
        return !done_;
70
 
    }
71
 
 
72
 
    void remove(MyQuery const* query)
73
 
    {
74
 
        std::lock_guard<std::mutex> lock(mutex_);
75
 
        QueryData qd { query, "", nullptr };
76
 
        auto it = std::find(queries_.begin(), queries_.end(), qd);
77
 
        if (it != queries_.end())
78
 
        {
79
 
            cerr << "Queue: removed query: " << it->query_string << endl;
80
 
            queries_.erase(it);
81
 
        }
82
 
        else
83
 
        {
84
 
            cerr << "Queue: did not find entry to be removed" << endl;
85
 
        }
86
 
    }
87
 
 
88
 
    void finish()
89
 
    {
90
 
        std::unique_lock<std::mutex> lock(mutex_);
91
 
        queries_.clear();
92
 
        done_ = true;
93
 
        condvar_.notify_all();
94
 
    }
95
 
 
96
 
    Queue()
97
 
        : done_(false)
98
 
    {
99
 
    }
100
 
 
101
 
private:
102
 
    struct QueryData
103
 
    {
104
 
        MyQuery const* query;
105
 
        string query_string;
106
 
        ReplyProxy reply_proxy;
107
 
 
108
 
        bool operator==(QueryData const& rhs) const
109
 
        {
110
 
            return query == rhs.query;
111
 
        }
112
 
    };
113
 
 
114
 
    std::list<QueryData> queries_;
115
 
    bool done_;
116
 
    std::mutex mutex_;
117
 
    std::condition_variable condvar_;
118
 
};
119
 
 
120
 
// Example scope C: Does not use the query's run() method other than to remember the query.
121
 
// The run() method of the scope acts as a worker thread to push replies to remembered queries.
122
 
// This example shows that letting run() return immediately is OK, and that the MyQuery instance stays
123
 
// alive as long as it can still be cancelled, which is while there is at least one
124
 
// ReplyProxy still in existence for this query.
125
 
 
126
 
class MyQuery : public QueryBase
127
 
{
128
 
public:
129
 
    MyQuery(string const& query, Queue& queue) :
130
 
        query_(query),
131
 
        queue_(queue)
132
 
    {
133
 
        cerr << "My Query created" << endl;
134
 
    }
135
 
 
136
 
    ~MyQuery() noexcept
137
 
    {
138
 
        cerr << "My Query destroyed" << endl;
139
 
    }
140
 
 
141
 
    virtual void cancelled() override
142
 
    {
143
 
        // Remove this query from the queue, if it is still there.
144
 
        // If it isn't, and the worker thread is still working on this
145
 
        // query, the worker thread's next call to push() will return false,
146
 
        // causing the worker thread to stop working on this query.
147
 
        queue_.remove(this);
148
 
        cerr << "scope-C: \"" + query_ + "\" cancelled" << endl;
149
 
    }
150
 
 
151
 
    virtual void run(ReplyProxy const& reply) override
152
 
    {
153
 
        queue_.put(this, query_, reply);
154
 
        cerr << "scope-C: run() returning" << endl;
155
 
    }
156
 
 
157
 
private:
158
 
    string query_;
159
 
    Queue& queue_;
160
 
};
161
 
 
162
 
class MyScope : public ScopeBase
163
 
{
164
 
public:
165
 
    virtual int start(string const& scope_name, RegistryProxy const&) override
166
 
    {
167
 
        scope_name_ = scope_name;
168
 
        return VERSION;
169
 
    }
170
 
 
171
 
    virtual void stop() override
172
 
    {
173
 
        queue.finish();
174
 
    }
175
 
 
176
 
    virtual void run() override
177
 
    {
178
 
        for (;;)
179
 
        {
180
 
            string query;
181
 
            ReplyProxy reply;
182
 
            if (!queue.get(query, reply))
183
 
            {
184
 
                cerr << "worker thread terminating, queue was cleared" << endl;
185
 
                break;  // stop() was called.
186
 
            }
187
 
            for (int i = 1; i < 4; ++i)
188
 
            {
189
 
                cerr << "worker thread: pushing" << endl;
190
 
                auto cat = std::make_shared<Category>("cat1");
191
 
                ResultItem result(cat);
192
 
                result.set_uri("uri");
193
 
                result.set_title("scope-C: result " + to_string(i) + " for query \"" + query + "\"");
194
 
                result.set_icon("icon");
195
 
                result.set_dnd_uri("dnd_uri");
196
 
                if (!reply->push(result))
197
 
                {
198
 
                    cerr << "worker thread: push returned false" << endl;
199
 
                    break; // Query was cancelled
200
 
                }
201
 
                sleep(1);
202
 
            }
203
 
        }
204
 
    }
205
 
 
206
 
    virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
207
 
    {
208
 
        cout << scope_name_ << ": created query: \"" << q << "\"" << endl;
209
 
        return QueryBase::UPtr(new MyQuery(q, queue));
210
 
    }
211
 
 
212
 
private:
213
 
    string scope_name_;
214
 
    Queue queue;
215
 
};
216
 
 
217
 
extern "C"
218
 
{
219
 
 
220
 
    EXPORT
221
 
    unity::api::scopes::ScopeBase*
222
 
    // cppcheck-suppress unusedFunction
223
 
    UNITY_API_SCOPE_CREATE_FUNCTION()
224
 
    {
225
 
        return new MyScope;
226
 
    }
227
 
 
228
 
    EXPORT
229
 
    void
230
 
    // cppcheck-suppress unusedFunction
231
 
    UNITY_API_SCOPE_DESTROY_FUNCTION(unity::api::scopes::ScopeBase* scope_base)
232
 
    {
233
 
        delete scope_base;
234
 
    }
235
 
 
236
 
}