Back to index

unity  6.0.0
GLibSource.cpp
Go to the documentation of this file.
00001 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
00002 /*
00003 * Copyright (C) 2012 Canonical Ltd
00004 *
00005 * This program is free software: you can redistribute it and/or modify
00006 * it under the terms of the GNU General Public License version 3 as
00007 * published by the Free Software Foundation.
00008 *
00009 * This program is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 * GNU General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU General Public License
00015 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 *
00017 * Authored by: Marco Trevisan (TreviƱo) <3v1n0@ubuntu.com>
00018 */
00019 
00020 #include "GLibSource.h"
00021 #include <boost/lexical_cast.hpp>
00022 
00023 namespace unity
00024 {
00025 namespace glib
00026 {
00027 
00028 Source::Source()
00029   : source_(nullptr)
00030   , source_id_(0)
00031   , callback_data_(nullptr)
00032 {}
00033 
00034 Source::~Source()
00035 {
00036   Remove();
00037 
00038   if (callback_data_)
00039     callback_data_->self = nullptr;
00040 }
00041 
00042 void Source::Remove()
00043 {
00044   if (source_)
00045   {
00046     if (!g_source_is_destroyed(source_))
00047     {
00048       g_source_destroy(source_);
00049     }
00050 
00051     g_source_unref(source_);
00052     source_ = nullptr;
00053   }
00054 }
00055 
00056 void Source::SetPriority(Priority prio)
00057 {
00058   if (!source_)
00059     return;
00060 
00061   g_source_set_priority(source_, prio);
00062 }
00063 
00064 Source::Priority Source::GetPriority() const
00065 {
00066   int prio = 0;
00067   if (source_)
00068     prio = g_source_get_priority(source_);
00069 
00070   return static_cast<Priority>(prio);
00071 }
00072 
00073 bool Source::Run(SourceCallback callback)
00074 {
00075   if (!source_ || source_id_ || IsRunning())
00076     return false;
00077 
00078   callback_ = callback;
00079   callback_data_ = new CallBackData(this);
00080 
00081   g_source_set_callback(source_, Callback, callback_data_, DestroyCallback);
00082   source_id_ = g_source_attach(source_, nullptr);
00083 
00084   return true;
00085 }
00086 
00087 bool Source::IsRunning() const
00088 {
00089   if (!source_)
00090     return false;
00091 
00092   return (!g_source_is_destroyed(source_) && g_source_get_context(source_));
00093 }
00094 
00095 unsigned int Source::Id() const
00096 {
00097   return source_id_;
00098 }
00099 
00100 gboolean Source::Callback(gpointer data)
00101 {
00102   if (!data)
00103     return G_SOURCE_REMOVE;
00104 
00105   auto self = static_cast<CallBackData*>(data)->self;
00106 
00107   if (self && !self->callback_.empty() && self->callback_())
00108   {
00109     return G_SOURCE_CONTINUE;
00110   }
00111   else
00112   {
00113     return G_SOURCE_REMOVE;
00114   }
00115 }
00116 
00117 void Source::DestroyCallback(gpointer data)
00118 {
00119   if (!data)
00120     return;
00121 
00122   auto cb_data = static_cast<CallBackData*>(data);
00123 
00124   if (cb_data->self)
00125   {
00126     auto self = cb_data->self;
00127     self->callback_data_ = nullptr;
00128 
00129     if (self->Id())
00130       self->removed.emit(self->Id());
00131   }
00132 
00133   delete cb_data;
00134 }
00135 
00136 
00137 Timeout::Timeout(unsigned int milliseconds, SourceCallback cb, Priority prio)
00138 {
00139   Init(milliseconds, prio);
00140   Run(cb);
00141 }
00142 
00143 Timeout::Timeout(unsigned int milliseconds, Priority prio)
00144 {
00145   Init(milliseconds, prio);
00146 }
00147 
00148 void Timeout::Init(unsigned int milliseconds, Priority prio)
00149 {
00150   source_ = g_timeout_source_new(milliseconds);
00151   SetPriority(prio);
00152 }
00153 
00154 
00155 TimeoutSeconds::TimeoutSeconds(unsigned int seconds, SourceCallback cb, Priority prio)
00156 {
00157   Init(seconds, prio);
00158   Run(cb);
00159 }
00160 
00161 TimeoutSeconds::TimeoutSeconds(unsigned int seconds, Priority prio)
00162 {
00163   Init(seconds, prio);
00164 }
00165 
00166 void TimeoutSeconds::Init(unsigned int seconds, Priority prio)
00167 {
00168   source_ = g_timeout_source_new_seconds(seconds);
00169   SetPriority(prio);
00170 }
00171 
00172 
00173 Idle::Idle(SourceCallback cb, Priority prio)
00174 {
00175   Init(prio);
00176   Run(cb);
00177 }
00178 
00179 Idle::Idle(Priority prio)
00180 {
00181   Init(prio);
00182 }
00183 
00184 void Idle::Init(Priority prio)
00185 {
00186   source_ = g_idle_source_new();
00187   SetPriority(prio);
00188 }
00189 
00190 
00191 SourceManager::SourceManager()
00192 {}
00193 
00194 SourceManager::~SourceManager()
00195 {
00196   for (auto it = sources_.begin(); it != sources_.end();)
00197   {
00198     RemoveItem(it++);
00199   }
00200 }
00201 
00202 bool SourceManager::Add(Source* source, std::string const& nick)
00203 {
00204   Source::Ptr s(source);
00205   return Add(s, nick);
00206 }
00207 
00208 bool SourceManager::Add(Source::Ptr const& source, std::string const& nick)
00209 {
00210   if (!source)
00211     return false;
00212 
00213   /* If the manager controls another source equal to the one we're passing,
00214    * we don't add it again */
00215   for (auto it : sources_)
00216   {
00217     if (it.second == source)
00218     {
00219       return false;
00220     }
00221   }
00222 
00223   std::string source_nick(nick);
00224 
00225   if (source_nick.empty())
00226   {
00227     /* If we don't have a nick, we use the source pointer string as nick. */
00228     source_nick = boost::lexical_cast<std::string>(source.get());
00229   }
00230 
00231   auto old_source_it = sources_.find(source_nick);
00232   if (old_source_it != sources_.end())
00233   {
00234     /* If a source with the same nick has been found, we can safely replace it,
00235      * since at this point we're sure that they refers to two different sources.
00236      * This should not happen when we're trying to re-add the same source from
00237      * its callback. */
00238     RemoveItem(old_source_it);
00239   }
00240 
00241   sources_[source_nick] = source;
00242   source->removed.connect(sigc::mem_fun(this, &SourceManager::OnSourceRemoved));
00243 
00244   return true;
00245 }
00246 
00247 void SourceManager::OnSourceRemoved(unsigned int id)
00248 {
00249   for (auto it = sources_.begin(); it != sources_.end(); ++it)
00250   {
00251     auto source = it->second;
00252 
00253     if (source->Id() == id)
00254     {
00255       sources_.erase(it);
00256       break;
00257     }
00258   }
00259 }
00260 
00261 bool SourceManager::Remove(std::string const& nick)
00262 {
00263   auto it = sources_.find(nick);
00264 
00265   if (it != sources_.end())
00266   {
00267     RemoveItem(it);
00268     return true;
00269   }
00270 
00271   return false;
00272 }
00273 
00274 bool SourceManager::Remove(unsigned int id)
00275 {
00276   for (auto it = sources_.begin(); it != sources_.end(); ++it)
00277   {
00278     auto source = it->second;
00279 
00280     if (source->Id() == id)
00281     {
00282       RemoveItem(it);
00283       return true;
00284     }
00285   }
00286 
00287   return false;
00288 }
00289 
00290 void SourceManager::RemoveItem(SourcesMap::iterator it)
00291 {
00292   auto source = it->second;
00293 
00294   source->removed.clear();
00295   source->Remove();
00296   sources_.erase(it);
00297 }
00298 
00299 Source::Ptr SourceManager::GetSource(unsigned int id) const
00300 {
00301   for (auto it : sources_)
00302   {
00303     if (it.second->Id() == id)
00304     {
00305       return it.second;
00306     }
00307   }
00308 
00309   return Source::Ptr();
00310 }
00311 
00312 Source::Ptr SourceManager::GetSource(std::string const& nick) const
00313 {
00314   auto it = sources_.find(nick);
00315 
00316   if (it != sources_.end())
00317   {
00318     return it->second;
00319   }
00320 
00321   return Source::Ptr();
00322 }
00323 
00324 }
00325 }