<commit_before>/*
**  Copyright (C) 2012 <NAME>
**  See COPYING for the license
*/
#include <map>
#include <qi/atomic.hpp>

#include <boost/thread/recursive_mutex.hpp>
#include <boost/make_shared.hpp>

#include <qitype/signal.hpp>
#include <qitype/genericvalue.hpp>
#include <qitype/genericobject.hpp>

#include "object_p.hpp"
#include "signal_p.hpp"

namespace qi {

  SignalSubscriber::SignalSubscriber(qi::ObjectPtr target, unsigned int method)
  : weakLock(0), threadingModel(MetaCallType_Direct),  target(new qi::ObjectWeakPtr(target)), method(method), enabled(true)
  { // The slot has its own threading model: be synchronous
  }



  SignalSubscriber::SignalSubscriber(GenericFunction func, MetaCallType model, detail::WeakLock* lock)
     : handler(func), weakLock(lock), threadingModel(model), target(0), method(0), enabled(true)
   {
   }

  SignalSubscriber::~SignalSubscriber()
  {
    delete target;
    delete weakLock;
  }

  SignalSubscriber::SignalSubscriber(const SignalSubscriber& b)
  : weakLock(0), target(0)
  {
    *this = b;
  }

  void SignalSubscriber::operator=(const SignalSubscriber& b)
  {
    source = b.source;
    linkId = b.linkId;
    handler = b.handler;
    weakLock = b.weakLock?b.weakLock->clone():0;
    threadingModel = b.threadingModel;
    target = b.target?new ObjectWeakPtr(*b.target):0;
    method = b.method;
    enabled = b.enabled;
  }

  static qi::Atomic<int> linkUid = 1;

  void SignalBase::setCallType(MetaCallType callType)
  {
    if (!_p)
    {
      _p = boost::shared_ptr<SignalBasePrivate>(new SignalBasePrivate());
    }
    _p->defaultCallType = callType;
  }

  void SignalBase::operator()(
      qi::AutoGenericValuePtr p1,
      qi::AutoGenericValuePtr p2,
      qi::AutoGenericValuePtr p3,
      qi::AutoGenericValuePtr p4,
      qi::AutoGenericValuePtr p5,
      qi::AutoGenericValuePtr p6,
      qi::AutoGenericValuePtr p7,
      qi::AutoGenericValuePtr p8)
  {
    qi::AutoGenericValuePtr* vals[8]= {&p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8};
    std::vector<qi::GenericValuePtr> params;
    for (unsigned i = 0; i < 8; ++i)
      if (vals[i]->value)
        params.push_back(*vals[i]);
    // Signature construction
    std::string signature = "(";
    for (unsigned i=0; i< params.size(); ++i)
      signature += params[i].signature();
    signature += ")";
    if (signature != _p->signature)
    {
      qiLogError("qi.signal") << "Dropping emit: signature mismatch: " << signature <<" " << _p->signature;
      return;
    }
    trigger(params, _p->defaultCallType);
  }

  void SignalBase::trigger(const GenericFunctionParameters& params, MetaCallType callType)
  {
    if (!_p)
      return;

    SignalSubscriberMap copy;
    {
      boost::recursive_mutex::scoped_lock sl(_p->mutex);
      copy = _p->subscriberMap;
    }

    SignalSubscriberMap::iterator i;
    for (i = copy.begin(); i != copy.end(); ++i)
    {
      SignalSubscriberPtr s = i->second; // hold s alive
      s->call(params, callType);
    }
  }

  class FunctorCall
  {
  public:
    FunctorCall(GenericFunctionParameters& params, SignalSubscriberPtr sub)
    : sub(sub)
    {
      std::swap((std::vector<GenericValuePtr>&)this->params, (std::vector<GenericValuePtr>&)params);
    }

    FunctorCall(const FunctorCall& b)
    {
      *this = b;
    }

    void operator=(const FunctorCall& b)
    {
      std::swap((std::vector<GenericValuePtr>&)(this->params),
        (std::vector<GenericValuePtr>&)b.params);
      sub = b.sub;
    }

    void operator() ()
    {
      {
        boost::mutex::scoped_lock sl(sub->mutex);
        // verify-enabled-then-register-active op must be locked
        if (!sub->enabled)
          return;
        sub->addActive(false);
      }
      sub->handler(params);
      sub->removeActive(true);
      params.destroy();
      if (sub->weakLock)
        sub->weakLock->unlock();
    }

  public:
    GenericFunctionParameters params;
    SignalSubscriberPtr         sub;
  };

  void SignalSubscriber::call(const GenericFunctionParameters& args, MetaCallType callType)
  {
    // this is held alive by caller
    if (handler.type)
    {
      // Try to acquire weakLock, for both the sync and async cases
      if (weakLock)
      {
        bool locked = weakLock->tryLock();
        if (!locked)
        {
          source->disconnect(linkId);
          return;
        }
      }
      bool async = true;
      if (threadingModel != MetaCallType_Auto)
        async = (threadingModel == MetaCallType_Queued);
      else if (callType != MetaCallType_Auto)
        async = (callType == MetaCallType_Queued);

      (callType == MetaCallType_Queued || threadingModel == MetaCallType_Queued);
      qiLogDebug("qi.Signal") << "subscriber call async=" << async <<" ct " << callType <<" tm " << threadingModel;
      if (async)
      {
        GenericFunctionParameters copy = args.copy();
        // We will check enabled when we will be scheduled in the target
        // thread, and we hold this SignalSubscriber alive, so no need to
        // explicitly track the asynccall
        getDefaultThreadPoolEventLoop()->post(FunctorCall(copy, shared_from_this()));
      }
      else
      {
        // verify-enabled-then-register-active op must be locked
        {
          boost::mutex::scoped_lock sl(mutex);
          if (!enabled)
            return;
          addActive(false);
        }
        handler(args);
        if (weakLock)
          weakLock->unlock();
        removeActive(true);
      }
    }
    else if (target)
    {
      ObjectPtr lockedTarget = target->lock();<commit_msg>Remove useless statement<commit_after>/*
**  Copyright (C) 2012 <NAME>
**  See COPYING for the license
*/
#include <map>
#include <qi/atomic.hpp>

#include <boost/thread/recursive_mutex.hpp>
#include <boost/make_shared.hpp>

#include <qitype/signal.hpp>
#include <qitype/genericvalue.hpp>
#include <qitype/genericobject.hpp>

#include "object_p.hpp"
#include "signal_p.hpp"

namespace qi {

  SignalSubscriber::SignalSubscriber(qi::ObjectPtr target, unsigned int method)
  : weakLock(0), threadingModel(MetaCallType_Direct),  target(new qi::ObjectWeakPtr(target)), method(method), enabled(true)
  { // The slot has its own threading model: be synchronous
  }



  SignalSubscriber::SignalSubscriber(GenericFunction func, MetaCallType model, detail::WeakLock* lock)
     : handler(func), weakLock(lock), threadingModel(model), target(0), method(0), enabled(true)
   {
   }

  SignalSubscriber::~SignalSubscriber()
  {
    delete target;
    delete weakLock;
  }

  SignalSubscriber::SignalSubscriber(const SignalSubscriber& b)
  : weakLock(0), target(0)
  {
    *this = b;
  }

  void SignalSubscriber::operator=(const SignalSubscriber& b)
  {
    source = b.source;
    linkId = b.linkId;
    handler = b.handler;
    weakLock = b.weakLock?b.weakLock->clone():0;
    threadingModel = b.threadingModel;
    target = b.target?new ObjectWeakPtr(*b.target):0;
    method = b.method;
    enabled = b.enabled;
  }

  static qi::Atomic<int> linkUid = 1;

  void SignalBase::setCallType(MetaCallType callType)
  {
    if (!_p)
    {
      _p = boost::shared_ptr<SignalBasePrivate>(new SignalBasePrivate());
    }
    _p->defaultCallType = callType;
  }

  void SignalBase::operator()(
      qi::AutoGenericValuePtr p1,
      qi::AutoGenericValuePtr p2,
      qi::AutoGenericValuePtr p3,
      qi::AutoGenericValuePtr p4,
      qi::AutoGenericValuePtr p5,
      qi::AutoGenericValuePtr p6,
      qi::AutoGenericValuePtr p7,
      qi::AutoGenericValuePtr p8)
  {
    qi::AutoGenericValuePtr* vals[8]= {&p1, &p2, &p3, &p4, &p5, &p6, &p7, &p8};
    std::vector<qi::GenericValuePtr> params;
    for (unsigned i = 0; i < 8; ++i)
      if (vals[i]->value)
        params.push_back(*vals[i]);
    // Signature construction
    std::string signature = "(";
    for (unsigned i=0; i< params.size(); ++i)
      signature += params[i].signature();
    signature += ")";
    if (signature != _p->signature)
    {
      qiLogError("qi.signal") << "Dropping emit: signature mismatch: " << signature <<" " << _p->signature;
      return;
    }
    trigger(params, _p->defaultCallType);
  }

  void SignalBase::trigger(const GenericFunctionParameters& params, MetaCallType callType)
  {
    if (!_p)
      return;

    SignalSubscriberMap copy;
    {
      boost::recursive_mutex::scoped_lock sl(_p->mutex);
      copy = _p->subscriberMap;
    }

    SignalSubscriberMap::iterator i;
    for (i = copy.begin(); i != copy.end(); ++i)
    {
      SignalSubscriberPtr s = i->second; // hold s alive
      s->call(params, callType);
    }
  }

  class FunctorCall
  {
  public:
    FunctorCall(GenericFunctionParameters& params, SignalSubscriberPtr sub)
    : sub(sub)
    {
      std::swap((std::vector<GenericValuePtr>&)this->params, (std::vector<GenericValuePtr>&)params);
    }

    FunctorCall(const FunctorCall& b)
    {
      *this = b;
    }

    void operator=(const FunctorCall& b)
    {
      std::swap((std::vector<GenericValuePtr>&)(this->params),
        (std::vector<GenericValuePtr>&)b.params);
      sub = b.sub;
    }

    void operator() ()
    {
      {
        boost::mutex::scoped_lock sl(sub->mutex);
        // verify-enabled-then-register-active op must be locked
        if (!sub->enabled)
          return;
        sub->addActive(false);
      }
      sub->handler(params);
      sub->removeActive(true);
      params.destroy();
      if (sub->weakLock)
        sub->weakLock->unlock();
    }

  public:
    GenericFunctionParameters params;
    SignalSubscriberPtr         sub;
  };

  void SignalSubscriber::call(const GenericFunctionParameters& args, MetaCallType callType)
  {
    // this is held alive by caller
    if (handler.type)
    {
      // Try to acquire weakLock, for both the sync and async cases
      if (weakLock)
      {
        bool locked = weakLock->tryLock();
        if (!locked)
        {
          source->disconnect(linkId);
          return;
        }
      }
      bool async = true;
      if (threadingModel != MetaCallType_Auto)
        async = (threadingModel == MetaCallType_Queued);
      else if (callType != MetaCallType_Auto)
        async = (callType == MetaCallType_Queued);

      qiLogDebug("qi.Signal") << "subscriber call async=" << async <<" ct " << callType <<" tm " << threadingModel;
      if (async)
      {
        GenericFunctionParameters copy = args.copy();
        // We will check enabled when we will be scheduled in the target
        // thread, and we hold this SignalSubscriber alive, so no need to
        // explicitly track the asynccall
        getDefaultThreadPoolEventLoop()->post(FunctorCall(copy, shared_from_this()));
      }
      else
      {
        // verify-enabled-then-register-active op must be locked
        {
          boost::mutex::scoped_lock sl(mutex);
          if (!enabled)
            return;
          addActive(false);
        }
        handler(args);
        if (weakLock)
          weakLock->unlock();
        removeActive(true);
      }
    }
    else if (target)
    {
      ObjectPtr lockedTarget = target->lock();
{'fraction_non_alphanumeric': 0.1329302409529826, 'fraction_numerical': 0.005775652016965978, 'mean_word_length': 2.824016563146998, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7341148', 'n_tokens_mistral': 3605, 'n_tokens_neox': 3468, 'n_words': 743}