void CreateDiscussionsHandler::handleIqID( const IQ& iq, int context )
	{
		json::jobject jobj;
		if (iq.m_subtype != gloox::IQ::Result)
		{
			universal_resource error_desc;
			ELOG("app")->error(WCOOL(L"创建讨论组时服务端返回错误。") + boost::shared_ptr<gloox::Tag>(iq.tag())->xml());
			error_desc = XL("biz.CreateDiscussions.fail");

			callback_(true, error_desc, jobj);
		}else{
			if(iq.findExtension(kExtUser_iq_filter_creatediscussions))
			{
				boost::shared_ptr<gloox::Tag> tag(iq.findExtension(kExtUser_iq_filter_creatediscussions)->tag());
				if (tag)
				{
					gloox::Tag* tag2 = tag->findChild("item");
					if (tag)
					{
						jobj["session_id"] = gWrapInterface::instance().append_discussions_domain(tag2->findAttribute("id"));
						jobj["group_name"] = tag2->findAttribute("topic");

						callback_(false,XL(""),jobj);
						return;
					}
				}
			}
			ELOG("app")->error(WCOOL(L"创建讨论组时服务端返回的数据格式错误。") + boost::shared_ptr<gloox::Tag>(iq.tag())->xml());
			callback_(true, XL("biz.CreateDiscussions.fail"), jobj);
		}
	}
	void GroupsAdminManageMemberHandler::handleIqID( const IQ& iq, int context )
	{
		json::jobject jobj;
		if (iq.m_subtype != gloox::IQ::Result)
		{
			const Error* e = iq.error();
			if (!e)
			{
				callback_(true,XL("biz.GroupsAdminManageMember.fail"));
				return;
			}
			if ( e->error() == StanzaErrorBadRequest)
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,请求协议错误!。"));
				callback_(true,XL("biz.crwod.iq_error.bad-request"));
			}
			else if (e->error() == StanzaErrorInternalServerError)
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,处理错误(服务器处理错误)。"));
				callback_(true,XL("biz.crwod.iq_error.internal-server-error"));
			}
			else if (e->error() == StanzaErrorGone)
			{
				universal_resource err;
				err.res_key="biz.crwod.iq_error.answer_apply_gone";
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,消息已过期!"));
				callback_(false,err);
			}
			else if (e->error() == StanzaErrorForbidden)
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,自己不是管理员"));
				callback_(true,XL("biz.crwod.iq_error.admin_forbidden"));
			}			
			else if (e->error() == StanzaErrorResourceConstraint)
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,群成员已经满"));
				callback_(true,XL("biz.crwod.iq_error.admin_resource-constraint"));
			}
			else if (e->error() == StanzaErrorConflict)
			{
				universal_resource err;
				err.res_key="biz.crwod.iq_error.admin_Conflict";
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,该成员已加入群"));
				callback_(false,err);
			}
			else if (e->error() == StanzaErrorItemNotFound)
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,找不到此群。"));
				callback_(true,XL("biz.crwod.iq_error.item-not-found"));
			}else
			{
				ELOG("app")->error(WCOOL(L"管理员审批成员加入时,服务器返回未知错误类型!") + boost::shared_ptr<gloox::Tag>(iq.tag())->xml());
				callback_(true,XL("biz.GroupsAdminManageMember.fail"));
			}

		}else{
			callback_(false,XL(""));		
		}
	}
	void ChangeDiscussionsNameHandler::handleIqID( const IQ& iq, int context )
	{
		json::jobject jobj;
		if (iq.m_subtype != gloox::IQ::Result)
		{
			universal_resource error_desc;
			ELOG("app")->error(WCOOL(L"讨论组改名时服务端返回错误。") + boost::shared_ptr<gloox::Tag>(iq.tag())->xml());
			error_desc = XL("biz.ChangeDiscussionsName.fail");
			callback_(true, error_desc);
		}
		else
		{
			callback_(false, XL(""));
		}
	}
Esempio n. 4
0
// StatusMgr
bool StatusMgr::Get(bool bLockFile) {
  if (!m_statusFile.IsOpen()) {
    m_statusFile.SetName(datadir_, STATUS_DAT);
    int nLockMode = (bLockFile) ? (File::modeReadWrite | File::modeBinary) : (File::modeReadOnly | File::modeBinary);
    m_statusFile.Open(nLockMode);
  } else {
    m_statusFile.Seek(0L, File::seekBegin);
  }
  if (!m_statusFile.IsOpen()) {
    return false;
  } else {
    char oldFileChangeFlags[7];
    for (int nFcIndex = 0; nFcIndex < 7; nFcIndex++) {
      oldFileChangeFlags[nFcIndex] = statusrec.filechange[nFcIndex];
    }
    m_statusFile.Read(&statusrec, sizeof(statusrec_t));

    if (!bLockFile) {
      m_statusFile.Close();
    }

    for (int i = 0; i < 7; i++) {
      if (oldFileChangeFlags[i] != statusrec.filechange[i]) {
        // Invoke callback on changes.
        callback_(i);
      }
    }
  }
  return true;
}
Esempio n. 5
0
 void DiskWriteTask::Cancel()
 {
     if (callback_)
     {
         callback_(ErrorCodes::ServiceBusy, this->resource_identifier_);
     }
 }
Esempio n. 6
0
void AudioRecorder::ProcessSLCallback(SLAndroidSimpleBufferQueueItf bq) {
#ifdef ENABLE_LOG
    recLog_->logTime();
#endif
    assert(bq == recBufQueueItf_);
    sample_buf *dataBuf = NULL;
    devShadowQueue_->front(&dataBuf);
    devShadowQueue_->pop();
    dataBuf->size_ = dataBuf->cap_;           //device only calls us when it is really full
    recQueue_->push(dataBuf);

    sample_buf* freeBuf;
    while (freeQueue_->front(&freeBuf) && devShadowQueue_->push(freeBuf)) {
        freeQueue_->pop();
        SLresult result = (*bq)->Enqueue(bq, freeBuf->buf_, freeBuf->cap_);
        SLASSERT(result);
    }

    /*
     * PLAY_KICKSTART_BUFFER_COUNT: # of buffers cached in the queue before
     * STARTING player. it is defined in audio_common.h. Whatever buffered
     * here is the part of the audio LATENCY! adjust to fit your bill [ until
     * it busts ]
     */
    if(++audioBufCount == PLAY_KICKSTART_BUFFER_COUNT && callback_) {
        callback_(ctx_, ENGINE_SERVICE_MSG_KICKSTART_PLAYER, NULL);
    }

    // should leave the device to sleep to save power if no buffers
    if (devShadowQueue_->size() == 0) {
        (*recItf_)->SetRecordState(recItf_, SL_RECORDSTATE_STOPPED);
    }
}
Esempio n. 7
0
// When On Expiration, Run Callback Function, And Reset next_ member
int Timer::ActivateCb(void *data) {
	tick_times_++;	
	// Invoke Callback
	int ret = callback_(data);
	// Refresh The Remaining Amount Time Util Next Expiration
	return ret;
}
Esempio n. 8
0
void PrimeSieve::doSmallPrime(const SmallPrime& sp)
{
  if (sp.firstPrime >= start_ && sp.lastPrime <= stop_)
  {
    // callback prime numbers
    if (sp.index == 0)
    {
      if (isFlag(CALLBACK_PRIMES_OBJ))
        cb_->callback(sp.firstPrime);
      if (isFlag(CALLBACK_PRIMES_OBJ_TN))
        cb_tn_->callback(sp.firstPrime, threadNum_);
      if (isFlag(CALLBACK_PRIMES))
        callback_(sp.firstPrime);
      if (isFlag(CALLBACK_PRIMES_TN))
        callback_tn_(sp.firstPrime, threadNum_);
      if (isFlag(CALLBACK_PRIMES_C))
        reinterpret_cast<callback_c_t>(callback_)(sp.firstPrime);
      if (isFlag(CALLBACK_PRIMES_C_TN))
        reinterpret_cast<callback_c_tn_t>(callback_tn_)(sp.firstPrime, threadNum_);
    }
    if (isCount(sp.index))
      counts_[sp.index]++;
    if (isPrint(sp.index))
      std::cout << sp.str << '\n';
  }
}
Esempio n. 9
0
void CallbackFunctionInternal::evalD(const double** arg,
                                     double** res, int* iw, double* w) {
    // Number of inputs and outputs
    int num_in = nIn();
    int num_out = nOut();

    std::vector<DMatrix> inputs(num_in);

    // Pass the inputs to the function
    for (int i=0; i<num_in; ++i) {
        inputs[i] = DMatrix::zeros(input(i).sparsity());
        if (arg[i] != 0) {
            inputs[i].setNZ(arg[i]);
        } else {
            inputs[i].set(0.);
        }
    }

    std::vector<DMatrix> outputs = callback_(inputs);

    // Get the outputs
    for (int i=0; i<num_out; ++i) {
        if (res[i] != 0) outputs[i].getNZ(res[i]);
    }
}
Esempio n. 10
0
void v1_3::Request::HandleContent(const std::string & url,
                                  const mf::http::Headers & headers,
                                  const std::string & content)
{
    assert(callback_);
    if (!callback_)
        return;

    ResponseType response;
    response.InitializeWithContent(url, "", headers, content);

    // These could possibly be available when an error occurs or on success.
    GetIfExists(response.pt, "response.pkey", &response.pkey);
    GetIfExists(response.pt, "response.secret_key", &response.secret_key);
    GetIfExists(response.pt, "response.time", &response.time);

    if (!response.error_code)
    {
        if (!GetIfExists(response.pt, "response.session_token",
                         &response.session_token))
        {
            response.error_code
                    = make_error_code(mf::api::api_code::ContentInvalidData);
            response.error_string = "missing session token";
        }
        if (!GetIfExists(response.pt, "response.ekey", &response.ekey))
        {
            response.error_code
                    = make_error_code(mf::api::api_code::ContentInvalidData);
            response.error_string = "missing \"response.ekey\"";
        }
    }

    callback_(response);
}
Esempio n. 11
0
 /**
  * Handle a new order message.
  *
  * New orders are added to the list of known orders and their qty is
  * added to the right book at the order's price level.
  *
  * @param recvts the timestamp when the message was received
  * @param msgcnt the number of messages received before this message
  * @param msgoffset the number of bytes received before this message
  * @param msg the message describing a new order
  */
 void handle_message(
     time_point recvts, long msgcnt, std::size_t msgoffset,
     add_order_message const& msg) {
   JB_LOG(trace) << " " << msgcnt << ":" << msgoffset << " " << msg;
   auto insert = orders_.emplace(
       msg.order_reference_number,
       order_data{msg.stock, msg.buy_sell_indicator, msg.price, msg.shares});
   if (insert.second == false) {
     // ... ooops, this should not happen, we got a duplicate order
     // id. There is a problem with the feed, because we are working
     // with simple command-line utilities we are just going to log the
     // error, in a more complex system we would want to raise an
     // exception and let the caller decide what to do ...
     order_data const& data = insert.first->second;
     JB_LOG(warning) << "duplicate order in handle_message(add_order_message)"
                     << ", id=" << msg.order_reference_number
                     << ", location=" << msgcnt << ":" << msgoffset
                     << ", existing data=" << data << ", msg=" << msg;
     return;
   }
   // ... find the right book for this order, create one if necessary ...
   auto& book = books_[msg.stock];
   (void)book.handle_add_order(msg.buy_sell_indicator, msg.price, msg.shares);
   callback_(
       msg.header, book, book_update{recvts, msg.stock, msg.buy_sell_indicator,
                                     msg.price, msg.shares});
 }
Esempio n. 12
0
void
Closure::Invoked() {
    if ( callback_ )
    {
        callback_();
    }
    else
    {
        // Only invoke the closure if the receiver still exists
        // Hint: If parent was destroyed, this closure would also be destroyed
        if ( parent() || !outOfThreadReceiver_.isNull() )
        {
            slot_.invoke(
                parent() ? parent() : outOfThreadReceiver_.data(),
                val0_ ? val0_->arg() : QGenericArgument(),
                val1_ ? val1_->arg() : QGenericArgument(),
                val2_ ? val2_->arg() : QGenericArgument(),
                val3_ ? val3_->arg() : QGenericArgument());
        }
    }

    if ( autoDelete_ )
    {
        deleteLater();
    }
}
Esempio n. 13
0
void
sanguis::client::control::input_translator::move_callback(
	sge::input::cursor::move_event const &_event
)
{
	callback_(
		sanguis::client::control::actions::any(
			sanguis::client::control::actions::variant(
				sanguis::client::control::actions::cursor(
					fcppt::optional::map(
						_event.position(),
						[](
							sge::input::cursor::position const _position
						)
						{
							return
								fcppt::math::vector::structure_cast<
									sanguis::client::control::cursor_position,
									fcppt::cast::size_fun
								>(
									_position
								);
						}
					)
				)
			)
		)
	);
}
Esempio n. 14
0
void Poll_t::handle_data()
{
    for(int i = 1; i <= maxi_; ++i)
    {
        int peerfd = client_[i].fd;
        if(client_[i].fd == -1)
            continue;
        if(client_[i].revents & POLLIN)
        {
            char buf[1024] = {0};
            int ret = readline(peerfd, buf, 1024);
            if(ret == -1)
            {
                ERR_EXIT("readline");
            }
            else if(ret == 0)
            {
                std::cout << "client close " << std::endl;
                del_fd(i);
                continue;
            }
            printf("%s\n",buf);
            callback_(peerfd, buf);
        } 
    }
}
    inline CallStatus handleDBusMessageReply(
            const CallStatus dbusMessageCallStatus,
            const DBusMessage& dbusMessage,
            index_sequence<ArgIndices_...>,
            std::tuple<ArgTypes_...> argTuple) const {
        (void)argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes
                        // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650

        CallStatus callStatus = dbusMessageCallStatus;

        if (dbusMessageCallStatus == CallStatus::SUCCESS) {
            if (!dbusMessage.isErrorType()) {
                DBusInputStream dbusInputStream(dbusMessage);
                const bool success
                    = DBusSerializableArguments<ArgTypes_...>::deserialize(
                            dbusInputStream,
                            std::get<ArgIndices_>(argTuple)...);
                if (!success)
                    callStatus = CallStatus::REMOTE_ERROR;
            } else {
                callStatus = CallStatus::REMOTE_ERROR;
            }
        }

        callback_(callStatus, std::move(std::get<ArgIndices_>(argTuple))...);
        return callStatus;
    }
Esempio n. 16
0
void AudioPlayer::ProcessSLCallback(SLAndroidSimpleBufferQueueItf bq) {
#ifdef ENABLE_LOG
    logFile_->logTime();
#endif
  std::lock_guard<std::mutex> lock(stopMutex_);

    // retrieve the finished device buf and put onto the free queue
    // so recorder could re-use it
    sample_buf *buf;
    if(!devShadowQueue_->front(&buf)) {
        /*
         * This should not happen: we got a callback,
         * but we have no buffer in deviceShadowedQueue
         * we lost buffers this way...(ERROR)
         */
        if(callback_) {
            uint32_t count;
            callback_(ctx_, ENGINE_SERVICE_MSG_RETRIEVE_DUMP_BUFS, &count);
        }
        return;
    }
    devShadowQueue_->pop();

    if( buf != &silentBuf_) {
        buf->size_ = 0;
        freeQueue_->push(buf);

        if (!playQueue_->front(&buf)) {
#ifdef ENABLE_LOG
          logFile->log("%s", "====Warning: running out of the Audio buffers")
#endif
          return;
        }
void v0::Request::HandleContent(
        const std::string & url,
        const mf::http::Headers & headers,
        const std::string & content)
{
    assert( callback_ );
    if ( ! callback_ )
        return;

    ResponseType response;
    response.InitializeWithContent(url, "", headers, content);

#   ifdef OUTPUT_DEBUG // Debug code
    std::cout << "Got content:\n" << content << std::endl;

    std::wostringstream ss;
    boost::property_tree::write_json( ss, response.pt );
    std::cout << "Got JSON:\n" << mf::utils::wide_to_bytes(ss.str()) << std::endl;
#   endif

    if ( ! response.error_code )
    {
        GetIfExists( response.pt, "response.pkey", &response.pkey );

        if ( ! GetIfExists( response.pt, "response.login_token",
                    &response.login_token ) )
        {
            response.error_code = make_error_code(
                    mf::api::api_code::ContentInvalidData );
            response.error_string = "missing session token";
        }
    }

    callback_(response);
}
Esempio n. 18
0
void Self::log(const LogLevel& level, std::string formatString,
               std::va_list args) const {
    if (enabled_ && callback_) {
        auto message = format(formatString, args);
        callback_(level, tag_, message);
    }
}
Esempio n. 19
0
void SampleAudioSource::getNextAudioBlock(const AudioSourceChannelInfo& buf) {
    ScopedLock l(lock_);
    if (not (source_ and isRunning_)) {
        buf.clearActiveBufferRegion();
        return;
    }

    currentTime_ += buf.numSamples;
    SampleTime overrun(currentTime_ - length_);
    if (overrun < 0) {
        source_->getNextAudioBlock(buf);
        panGainPlayer_->apply(buf);
        return;
    }

    AudioSourceChannelInfo b = buf;
    b.numSamples -= overrun;
    source_->getNextAudioBlock(b);
    panGainPlayer_->apply(b);
    b.startSample += b.numSamples;
    b.numSamples = overrun;
    b.clearActiveBufferRegion();
    isRunning_ = false;
    callback_(callbackData_);
    // Might block - perhaps we should do this in another thread?
}
Esempio n. 20
0
void C64::start()
{
  /* main emulator loop */
  while(true)
  {
#ifdef DEBUGGER_SUPPORT
    if(!debugger_->emulate())
      break;
#endif
    /* CIA1 */
    if(!cia1_->emulate())
      break;
    /* CIA2 */
    if(!cia2_->emulate())
      break;
    /* CPU */
    if(!cpu_->emulate())
      break;
    /* VIC-II */
    if(!vic_->emulate())
      break;
    /* IO */
    if(!io_->emulate())
      break;
    /* callback */
    if(callback_ && !callback_())
      break;
  }
}
Esempio n. 21
0
    void executorLoop()
    {
        TTimePoint call_end = nanos();
        while (started_) {
            TTimePoint period_start = nanos();
            TTimeDelta since_last_call = period_start - call_end;
            
            //is this first loop?
            if (period_count_ > 0) {
                //when we are doing work, don't let other thread to cause contention
                std::lock_guard<std::mutex> locker(mutex_);

                bool result = callback_(since_last_call);
                if (!result) {
                    started_ = result;
                }
            }
            
            call_end = nanos();

            TTimeDelta elapsed_period = nanos() - period_start;
            //prevent underflow: https://github.com/Microsoft/AirSim/issues/617
            TTimeDelta delay_nanos = period_nanos_ > elapsed_period ? period_nanos_ - elapsed_period : 0;
            //moving average of how much we are sleeping
            sleep_time_avg_ = 0.25f * sleep_time_avg_ + 0.75f * delay_nanos;
            ++period_count_;
            if (delay_nanos > 0 && started_)
                sleep_for(delay_nanos);
        }
    }
	virtual void onMessage(boost::shared_ptr<comminternal::PkgMsg> pMsgReq, boost::shared_ptr<google::protobuf::Message> message, boost::shared_ptr<comminternal::PkgSessionUser>pPkgSessionUser, const SessionCallBack callback) const
	{
		boost::shared_ptr<T> t = boost::dynamic_pointer_cast<T>(message);
		//T* t = dynamic_cast<T*>(message);
		assert(t != NULL);
		callback_(pMsgReq,t, pPkgSessionUser,callback);
	}
Esempio n. 23
0
session::~session()
{
  demux_.reset_mux();
  if (callback_)
  {
    callback_(session_event_t::ended);
  }
}
Esempio n. 24
0
void ElementGeometryClipper::visitWay(const Way& way)
{
    ClipperLib::Path wayShape;
    PointLocation pointLocation = setPath(quadKeyBbox_, way, wayShape);
    // 1. all geometry inside current quadkey: no need to truncate.
    if (pointLocation == PointLocation::AllInside) {
        callback_(way, quadKey_);
        return;
    }

    // 2. all geometry outside : way should be skipped
    if (pointLocation == PointLocation::AllOutside) {
        return;
    }

    ClipperLib::PolyTree solution;
    clipper_.AddPath(wayShape, ClipperLib::ptSubject, false);
    clipper_.AddPath(createPathFromBoundingBox(), ClipperLib::ptClip, true);
    clipper_.Execute(ClipperLib::ctIntersection, solution);
    clipper_.Clear();
    std::size_t count = static_cast<std::size_t>(solution.Total());

    // 3. way intersects border only once: store a copy with clipped geometry
    if (count == 1) {
        Way clippedWay;
        setData(clippedWay, way, solution.GetFirst()->Contour);
        callback_(clippedWay, quadKey_);
    }
        // 4. in this case, result should be stored as relation (collection of ways)
    else {
        Relation relation;
        relation.id = way.id;
        relation.tags = way.tags;
        relation.elements.reserve(count);
        ClipperLib::PolyNode* polyNode = solution.GetFirst();
        while (polyNode) {
            auto clippedWay = std::make_shared<Way>();
            clippedWay->id = way.id;
            setCoordinates(*clippedWay, polyNode->Contour);
            relation.elements.push_back(clippedWay);
            polyNode = polyNode->GetNext();
        }
        callback_(relation, quadKey_);
    }
}
Esempio n. 25
0
void ParticleFilter::update(double x, double y, double yaw)
{
  //============================== YOUR CODE HERE ==============================
  // Instructions: do one complete update of the particle filter. It should
  //               generate new particle set based on the given motion
  //               parameters and the old particle set, compute the weights of
  //               the particles, resample the set, and update the private
  //               member field that holds the current best pose estimate
  //               (pose_estimate_). Note that the motion parameters provided
  //               to this function are in robot's reference frame.
  //
  // Hint: to compute the weight of a particle, use the callback_ member field:
  //
  //           Particle particle;
  //           double weight = callback_(particle);
  //
  // Hint: to sample a uniformly distributed number in [min, max] range use:
  //
  //           double r = std::uniform_real_distribution<double>(min, max)(random_generator_);
  //

  //std::cout << "particles: size: " << particles_.size() << std::endl;


  // initialize resampling wheel
  std::vector<double> wheel;
  double total_weight = 0.0;

  motion_model_.setMotion(x, y, yaw);

  // get new pose for all particles based upon the motion model
  for ( uint i = 0; i < particle_set_size_; i++ ){
    particles_.at(i).pose = motion_model_.sample( particles_.at(i).pose );
    particles_.at(i).weight = callback_( particles_.at(i) );

    // add total weight to the resampling wheel
    total_weight = total_weight + particles_.at(i).weight;
    wheel.push_back( total_weight );
  }

  // resample particle set

  ParticleVector new_particle_set;
  double ran = std::uniform_real_distribution<double>(0.0, total_weight)(random_generator_);
  for (uint i = 0; i < particle_set_size_; i++) {
    for ( uint i = 0; i < wheel.size(); i++ ){
      if (ran > wheel.at(i)) {
        new_particle_set.push_back( particles_.at(i) );
      }
    }
  }




  //============================================================================
}
void TThread::Run()  
{
	SetState(TS_RUNNING);	
	if(nullptr != callback_)
    {  
        callback_(arg_); 
    }
	SetState(TS_TERMINATED);
}
Esempio n. 27
0
  // As soon as page flip, notify the client to draw the next frame.
  void DidPageFlip(int front_buffer,
                   unsigned int sec,
                   unsigned int usec) override {
    const Framebuffer& back_fb = framebuffers_[front_buffer ^ 1];

    glBindFramebuffer(GL_FRAMEBUFFER, back_fb.gl_fb);
    callback_(back_fb.gl_fb, sec * 1000000 + usec);
    EGLSyncFence();
  }
Esempio n. 28
0
	void wait() const
	{
		wg_future_status status;
		do
		{
			status = wait_for(std::chrono::microseconds(1));
			callback_();
		} while (status != std::future_status::ready);
	}
Esempio n. 29
0
int CLI::Command::invoke(int argc, char *argv[])
{
	Params params;

	for (int i = 0; i < argc; ++i)
		params.push_back(argv[i]);

	return callback_(params);
}
Esempio n. 30
0
void Button::call()
{
    if(value_.size() > 0)
        callback2_(value_);
    else if(node_)
        callback3_(node_);
    else
        callback_();
}