2
* Copyright (C) 2013 Canonical Ltd
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.
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.
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/>.
16
* Authored by: Michi Henning <michi.henning@canonical.com>
19
#include <scopes/ScopeBase.h>
20
#include <scopes/ResultItem.h>
21
#include <scopes/Category.h>
22
#include <scopes/Reply.h>
25
#include <condition_variable>
31
#define EXPORT __attribute__ ((visibility ("default")))
34
using namespace unity::api::scopes;
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.
47
void put(MyQuery const* query, string const& query_string, ReplyProxy const& reply_proxy)
50
std::lock_guard<std::mutex> lock(mutex_);
51
queries_.push_back(QueryData { query, query_string, reply_proxy });
53
condvar_.notify_one();
56
bool get(string& query_string, ReplyProxy& reply_proxy)
58
std::unique_lock<std::mutex> lock(mutex_);
59
condvar_.wait(lock, [this] { return !queries_.empty() || done_; });
63
condvar_.notify_all();
67
auto qd = queries_.front();
69
query_string = qd.query_string;
70
reply_proxy = qd.reply_proxy;
75
void remove(MyQuery const* query)
77
std::lock_guard<std::mutex> lock(mutex_);
78
QueryData qd { query, "", nullptr };
79
auto it = std::find(queries_.begin(), queries_.end(), qd);
80
if (it != queries_.end())
82
cerr << "Queue: removed query: " << it->query_string << endl;
87
cerr << "Queue: did not find entry to be removed" << endl;
94
std::unique_lock<std::mutex> lock(mutex_);
98
condvar_.notify_all();
109
MyQuery const* query;
111
ReplyProxy reply_proxy;
113
bool operator==(QueryData const& rhs) const
115
return query == rhs.query;
119
std::list<QueryData> queries_;
122
std::condition_variable condvar_;
125
// Example scope C: Does not use the query's run() method other than to remember the query.
126
// The run() method of the scope acts as a worker thread to push replies to remembered queries.
127
// This example shows that letting run() return immediately is OK, and that the MyQuery instance stays
128
// alive as long as it can still be cancelled, which is while there is at least one
129
// ReplyProxy still in existence for this query.
131
class MyQuery : public QueryBase
134
MyQuery(string const& query, Queue& queue) :
138
cerr << "My Query created" << endl;
143
cerr << "My Query destroyed" << endl;
146
virtual void cancelled() override
148
// Remove this query from the queue, if it is still there.
149
// If it isn't, and the worker thread is still working on this
150
// query, the worker thread's next call to push() will return false,
151
// causing the worker thread to stop working on this query.
153
cerr << "scope-C: \"" + query_ + "\" cancelled" << endl;
156
virtual void run(ReplyProxy const& reply) override
158
queue_.put(this, query_, reply);
159
cerr << "scope-C: run() returning" << endl;
167
class MyScope : public ScopeBase
170
virtual int start(string const& scope_name, RegistryProxy const&) override
172
scope_name_ = scope_name;
176
virtual void stop() override
181
virtual void run() override
187
if (!queue.get(query, reply))
189
cerr << "worker thread terminating, queue was cleared" << endl;
190
break; // stop() was called.
192
for (int i = 1; i < 4; ++i)
194
cerr << "worker thread: pushing" << endl;
195
auto cat = std::make_shared<Category>("cat1");
196
ResultItem result(cat);
197
result.set_uri("uri");
198
result.set_title("scope-C: result " + to_string(i) + " for query \"" + query + "\"");
199
result.set_icon("icon");
200
result.set_dnd_uri("dnd_uri");
201
if (!reply->push(result))
203
cerr << "worker thread: push returned false" << endl;
204
break; // Query was cancelled
211
virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
213
cout << scope_name_ << ": created query: \"" << q << "\"" << endl;
214
return QueryBase::UPtr(new MyQuery(q, queue));
226
unity::api::scopes::ScopeBase*
227
// cppcheck-suppress unusedFunction
228
UNITY_API_SCOPE_CREATE_FUNCTION()
235
// cppcheck-suppress unusedFunction
236
UNITY_API_SCOPE_DESTROY_FUNCTION(unity::api::scopes::ScopeBase* scope_base)