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)
49
std::lock_guard<std::mutex> lock(mutex_);
50
queries_.push_back(QueryData { query, query_string, reply_proxy });
51
condvar_.notify_one();
54
bool get(string& query_string, ReplyProxy& reply_proxy)
56
std::unique_lock<std::mutex> lock(mutex_);
57
condvar_.wait(lock, [this] { return !queries_.empty() || done_; });
60
condvar_.notify_all();
64
auto qd = queries_.front();
66
query_string = qd.query_string;
67
reply_proxy = qd.reply_proxy;
72
void remove(MyQuery const* query)
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())
79
cerr << "Queue: removed query: " << it->query_string << endl;
84
cerr << "Queue: did not find entry to be removed" << endl;
90
std::unique_lock<std::mutex> lock(mutex_);
93
condvar_.notify_all();
104
MyQuery const* query;
106
ReplyProxy reply_proxy;
108
bool operator==(QueryData const& rhs) const
110
return query == rhs.query;
114
std::list<QueryData> queries_;
117
std::condition_variable condvar_;
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.
126
class MyQuery : public QueryBase
129
MyQuery(string const& query, Queue& queue) :
133
cerr << "My Query created" << endl;
138
cerr << "My Query destroyed" << endl;
141
virtual void cancelled() override
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.
148
cerr << "scope-C: \"" + query_ + "\" cancelled" << endl;
151
virtual void run(ReplyProxy const& reply) override
153
queue_.put(this, query_, reply);
154
cerr << "scope-C: run() returning" << endl;
162
class MyScope : public ScopeBase
165
virtual int start(string const& scope_name, RegistryProxy const&) override
167
scope_name_ = scope_name;
171
virtual void stop() override
176
virtual void run() override
182
if (!queue.get(query, reply))
184
cerr << "worker thread terminating, queue was cleared" << endl;
185
break; // stop() was called.
187
for (int i = 1; i < 4; ++i)
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))
198
cerr << "worker thread: push returned false" << endl;
199
break; // Query was cancelled
206
virtual QueryBase::UPtr create_query(string const& q, VariantMap const&) override
208
cout << scope_name_ << ": created query: \"" << q << "\"" << endl;
209
return QueryBase::UPtr(new MyQuery(q, queue));
221
unity::api::scopes::ScopeBase*
222
// cppcheck-suppress unusedFunction
223
UNITY_API_SCOPE_CREATE_FUNCTION()
230
// cppcheck-suppress unusedFunction
231
UNITY_API_SCOPE_DESTROY_FUNCTION(unity::api::scopes::ScopeBase* scope_base)