<commit_before>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
#include "NdbUtil.hpp"
#include "NdbBlob.hpp"
#include "ndbapi_limits.h"
#include <signaldata/TcKeyReq.hpp>
#include "NdbDictionaryImpl.hpp"

#include "API.hpp"
#include <NdbOut.hpp>

/******************************************************************************
 * NdbOperation(Ndb* aNdb, Table* aTable);
 *
 * Return Value:  None
 * Parameters:    aNdb: Pointers to the Ndb object.
 *                aTable: Pointers to the Table object
 * Remark:        Creat an object of NdbOperation.
 ****************************************************************************/
NdbOperation::NdbOperation(Ndb* aNdb, NdbOperation::Type aType) :
  m_type(aType),
  theReceiver(aNdb),
  theErrorLine(0),
  theNdb(aNdb),
  //theTable(aTable),
  theNdbCon(NULL),
  theNext(NULL),
  theTCREQ(NULL),
  theFirstATTRINFO(NULL),
  theCurrentATTRINFO(NULL),
  theTotalCurrAI_Len(0),
  theAI_LenInCurrAI(0),
  theLastKEYINFO(NULL),

  theFirstLabel(NULL),
  theLastLabel(NULL),
  theFirstBranch(NULL),
  theLastBranch(NULL),
  theFirstCall(NULL),
  theLastCall(NULL),
  theFirstSubroutine(NULL),
  theLastSubroutine(NULL),
  theNoOfLabels(0),
  theNoOfSubroutines(0),

  m_currentTable(NULL), //theTableId(0xFFFF),
  m_accessTable(NULL), //theAccessTableId(0xFFFF),
  //theSchemaVersion(0),
  theTotalNrOfKeyWordInSignal(8),
  theTupKeyLen(0),
  theNoOfTupKeyLeft(0),
  theOperationType(NotDefined),
  theStatus(Init),
  theMagicNumber(0xFE11D0),
  theScanInfo(0),
  m_tcReqGSN(GSN_TCKEYREQ),
  m_keyInfoGSN(GSN_KEYINFO),
  m_attrInfoGSN(GSN_ATTRINFO),
  theBlobList(NULL),
  m_abortOption(-1)
{
  theReceiver.init(NdbReceiver::NDB_OPERATION, this);
  theError.code = 0;
}
/*****************************************************************************
 * ~NdbOperation();
 *
 * Remark:         Delete tables for connection pointers (id).
 *****************************************************************************/
NdbOperation::~NdbOperation( )
{
}
/******************************************************************************
 *void setErrorCode(int anErrorCode);
 *
 * Remark:         Set an Error Code on operation and
 *                 on connection set an error status.
 *****************************************************************************/
void
NdbOperation::setErrorCode(int anErrorCode)
{
  theError.code = anErrorCode;
  theNdbCon->theErrorLine = theErrorLine;
  theNdbCon->theErrorOperation = this;
  theNdbCon->setOperationErrorCode(anErrorCode);
}

/******************************************************************************
 * void setErrorCodeAbort(int anErrorCode);
 *
 * Remark:         Set an Error Code on operation and on connection set
 *                 an error status.
 *****************************************************************************/
void
NdbOperation::setErrorCodeAbort(int anErrorCode)
{
  theError.code = anErrorCode;
  theNdbCon->theErrorLine = theErrorLine;
  theNdbCon->theErrorOperation = this;
  theNdbCon->setOperationErrorCodeAbort(anErrorCode);
}

/*****************************************************************************
 * int init();
 *
 * Return Value:  Return 0 : init was successful.
 *                Return -1: In all other case.
 * Remark:        Initiates operation record after allocation.
 *****************************************************************************/

int
NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){
  NdbApiSignal* tSignal;
  theStatus		= Init;
  theError.code		= 0;
  theErrorLine		= 1;
  m_currentTable = m_accessTable = tab;

  theNdbCon = myConnection;
  for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++)
    for (int j=0; j<3; j++)
      theTupleKeyDefined[i][j] = 0;

  theFirstATTRINFO    = NULL;
  theCurrentATTRINFO  = NULL;
  theLastKEYINFO      = NULL;

  theTupKeyLen	    = 0;
  theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();

  theTotalCurrAI_Len	= 0;
  theAI_LenInCurrAI	= 0;
  theStartIndicator	= 0;
  theCommitIndicator	= 0;
  theSimpleIndicator	= 0;
  theDirtyIndicator	= 0;
  theInterpretIndicator	= 0;
  theDistrKeyIndicator_  = 0;
  theScanInfo        	= 0;
  theTotalNrOfKeyWordInSignal = 8;
  theMagicNumber        = 0xABCDEF01;
  theBlobList = NULL;
  m_abortOption = -1;
  m_no_disk_flag = 1;

  tSignal = theNdb->getSignal();
  if (tSignal == NULL)
  {
    setErrorCode(4000);
    return -1;
  }
  theTCREQ = tSignal;
  theTCREQ->setSignal(m_tcReqGSN);

  theAI_LenInCurrAI = 20;
  TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
  tcKeyReq->scanInfo = 0;
  theKEYINFOptr = &tcKeyReq->keyInfo[0];
  theATTRINFOptr = &tcKeyReq->attrInfo[0];
  theReceiver.init(NdbReceiver::NDB_OPERATION, this);
  return 0;
}

/******************************************************************************
 * void release();
 *
 * Remark:        Release all objects connected to the operation object.
 *****************************************************************************/
void
NdbOperation::release()
{
  NdbApiSignal* tSignal;
  NdbApiSignal* tSaveSignal;
  NdbBranch*	tBranch;
  NdbBranch*	tSaveBranch;
  NdbLabel*	tLabel;
  NdbLabel*	tSaveLabel;
  NdbCall*	tCall;
  NdbCall*	tSaveCall;
  NdbSubroutine* tSubroutine;
  NdbSubroutine* tSaveSubroutine;
  NdbBlob* tBlob;
  NdbBlob* tSaveBlob;

  tSignal = theTCREQ;
  while (tSignal != NULL)
  {
    tSaveSignal = tSignal;
    tSignal = tSignal->next();
    theNdb->releaseSignal(tSaveSignal);
  }
  theTCREQ = NULL;
  theLastKEYINFO = NULL;

  tSignal = theFirstATTRINFO;
  while (tSignal != NULL)
  {
    tSaveSignal = tSignal;
    tSignal = tSignal->next();
    theNdb->releaseSignal(tSaveSignal);
  }
  theFirstATTRINFO = NULL;
  theCurrentATTRINFO = NULL;

  if (theInterpretIndicator == 1)
  {
    tBranch = theFirstBranch;
    while (tBranch != NULL)
    {
      tSaveBranch = tBranch;
      tBranch = tBranch->theNext;
      theNdb->releaseNdbBranch(tSaveBranch);
    }
    tLabel = theFirstLabel;
    while (tLabel != NULL)
    {
      tSaveLabel = tLabel;
      tLabel = tLabel->theNext;
      theNdb->releaseNdbLabel(tSaveLabel);
    }
    tCall = theFirstCall;
    while (tCall != NULL)
    {
      tSaveCall = tCall;
      tCall = tCall->theNext;
      theNdb->releaseNdbCall(tSaveCall);
    }
    tSubroutine = theFirstSubroutine;
    while (tSubroutine != NULL)
    {
      tSaveSubroutine = tSubroutine;
      tSubroutine = tSubroutine->theNext;
      theNdb->releaseNdbSubroutine(tSaveSubroutine);
    }
  }
  tBlob = theBlobList;
  while (tBlob != NULL)
  {
    tSaveBlob = tBlob;
    tBlob = tBlob->theNext;
    theNdb->releaseNdbBlob(tSaveBlob);
  }
  theBlobList = NULL;
  theReceiver.release();
}

NdbRecAttr*
NdbOperation::getValue(const char* anAttrName, char* aValue)
{
  return getValue_impl(m_currentTable->getColumn(anAttrName), aValue);
}

NdbRecAttr*
NdbOperation::getValue(Uint32 anAttrId, char* aValue)
{
  return getValue_impl(m_currentTable->getColumn(anAttrId), aValue);
}

NdbRecAttr*
NdbOperation::getValue(const NdbDictionary::Column* col, char* aValue)
{
  return getValue_impl(&NdbColumnImpl::getImpl(*col), aValue);
}

int
NdbOperation::equal(const char* anAttrName, const char* aValuePassed)
{
  return equal_impl(m_accessTable->getColumn(anAttrName), aValuePassed);
}

int
NdbOperation::equal(Uint32 anAttrId, const char* aValuePassed)
{
  return equal_impl(m_accessTable->getColumn(anAttrId), aValuePassed);
}

int
NdbOperation::setValue(const char* anAttrName, const char* aValuePassed)
{
  return setValue(m_currentTable->getColumn(anAttrName), aValuePassed);
}

int
NdbOperation::setValue(Uint32 anAttrId, const char* aValuePassed)
{
  return setValue(m_currentTable->getColumn(anAttrId), aValuePassed);
}

NdbBlob*
NdbOperation::getBlobHandle(const char* anAttrName)
{
  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
  if (col == NULL)
  {
    setErrorCode(4004);
    return NULL;
  }
  else
  {
    return getBlobHandle(theNdbCon, col);
  }
}

NdbBlob*
NdbOperation::getBlobHandle(Uint32 anAttrId)
{
  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
  if (col == NULL)
  {
    setErrorCode(4004);
    return NULL;
  }
  else
  {
    return getBlobHandle(theNdbCon, col);
  }
}

int
NdbOperation::incValue(const char* anAttrName, Uint32 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::incValue(const char* anAttrName, Uint64 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::incValue(Uint32 anAttrId, Uint32 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::incValue(Uint32 anAttrId, Uint64 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::subValue( const char* anAttrName, Uint32 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::subValue(Uint32 anAttrId, Uint32 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::read_attr(const char* anAttrName, Uint32 RegDest)
{
  return read_attr(m_currentTable->getColumn(anAttrName), RegDest);
}

int
NdbOperation::read_attr(Uint32 anAttrId, Uint32 RegDest)
{
  return read_attr(m_currentTable->getColumn(anAttrId), RegDest);
}

int
NdbOperation::write_attr(const char* anAttrName, Uint32 RegDest)
{
  return write_attr(m_currentTable->getColumn(anAttrName), RegDest);
}

int
NdbOperation::write_attr(Uint32 anAttrId, Uint32 RegDest)
{
  return write_attr(m_currentTable->getColumn(anAttrId), RegDest);
}

const char*
NdbOperation::getTableName() const
{
  return m_currentTable->m_externalName.c_str();
}

const NdbDictionary::Table*
NdbOperation::getTable() const
{
  return m_currentTable;
}
<commit_msg>added missing prototype implementations (bug #25933)<commit_after>/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <ndb_global.h>
#include <NdbTransaction.hpp>
#include <NdbOperation.hpp>
#include "NdbApiSignal.hpp"
#include "NdbRecAttr.hpp"
#include "NdbUtil.hpp"
#include "NdbBlob.hpp"
#include "ndbapi_limits.h"
#include <signaldata/TcKeyReq.hpp>
#include "NdbDictionaryImpl.hpp"

#include "API.hpp"
#include <NdbOut.hpp>

/******************************************************************************
 * NdbOperation(Ndb* aNdb, Table* aTable);
 *
 * Return Value:  None
 * Parameters:    aNdb: Pointers to the Ndb object.
 *                aTable: Pointers to the Table object
 * Remark:        Creat an object of NdbOperation.
 ****************************************************************************/
NdbOperation::NdbOperation(Ndb* aNdb, NdbOperation::Type aType) :
  m_type(aType),
  theReceiver(aNdb),
  theErrorLine(0),
  theNdb(aNdb),
  //theTable(aTable),
  theNdbCon(NULL),
  theNext(NULL),
  theTCREQ(NULL),
  theFirstATTRINFO(NULL),
  theCurrentATTRINFO(NULL),
  theTotalCurrAI_Len(0),
  theAI_LenInCurrAI(0),
  theLastKEYINFO(NULL),

  theFirstLabel(NULL),
  theLastLabel(NULL),
  theFirstBranch(NULL),
  theLastBranch(NULL),
  theFirstCall(NULL),
  theLastCall(NULL),
  theFirstSubroutine(NULL),
  theLastSubroutine(NULL),
  theNoOfLabels(0),
  theNoOfSubroutines(0),

  m_currentTable(NULL), //theTableId(0xFFFF),
  m_accessTable(NULL), //theAccessTableId(0xFFFF),
  //theSchemaVersion(0),
  theTotalNrOfKeyWordInSignal(8),
  theTupKeyLen(0),
  theNoOfTupKeyLeft(0),
  theOperationType(NotDefined),
  theStatus(Init),
  theMagicNumber(0xFE11D0),
  theScanInfo(0),
  m_tcReqGSN(GSN_TCKEYREQ),
  m_keyInfoGSN(GSN_KEYINFO),
  m_attrInfoGSN(GSN_ATTRINFO),
  theBlobList(NULL),
  m_abortOption(-1)
{
  theReceiver.init(NdbReceiver::NDB_OPERATION, this);
  theError.code = 0;
}
/*****************************************************************************
 * ~NdbOperation();
 *
 * Remark:         Delete tables for connection pointers (id).
 *****************************************************************************/
NdbOperation::~NdbOperation( )
{
}
/******************************************************************************
 *void setErrorCode(int anErrorCode);
 *
 * Remark:         Set an Error Code on operation and
 *                 on connection set an error status.
 *****************************************************************************/
void
NdbOperation::setErrorCode(int anErrorCode)
{
  theError.code = anErrorCode;
  theNdbCon->theErrorLine = theErrorLine;
  theNdbCon->theErrorOperation = this;
  theNdbCon->setOperationErrorCode(anErrorCode);
}

/******************************************************************************
 * void setErrorCodeAbort(int anErrorCode);
 *
 * Remark:         Set an Error Code on operation and on connection set
 *                 an error status.
 *****************************************************************************/
void
NdbOperation::setErrorCodeAbort(int anErrorCode)
{
  theError.code = anErrorCode;
  theNdbCon->theErrorLine = theErrorLine;
  theNdbCon->theErrorOperation = this;
  theNdbCon->setOperationErrorCodeAbort(anErrorCode);
}

/*****************************************************************************
 * int init();
 *
 * Return Value:  Return 0 : init was successful.
 *                Return -1: In all other case.
 * Remark:        Initiates operation record after allocation.
 *****************************************************************************/

int
NdbOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection){
  NdbApiSignal* tSignal;
  theStatus		= Init;
  theError.code		= 0;
  theErrorLine		= 1;
  m_currentTable = m_accessTable = tab;

  theNdbCon = myConnection;
  for (Uint32 i=0; i<NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; i++)
    for (int j=0; j<3; j++)
      theTupleKeyDefined[i][j] = 0;

  theFirstATTRINFO    = NULL;
  theCurrentATTRINFO  = NULL;
  theLastKEYINFO      = NULL;

  theTupKeyLen	    = 0;
  theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();

  theTotalCurrAI_Len	= 0;
  theAI_LenInCurrAI	= 0;
  theStartIndicator	= 0;
  theCommitIndicator	= 0;
  theSimpleIndicator	= 0;
  theDirtyIndicator	= 0;
  theInterpretIndicator	= 0;
  theDistrKeyIndicator_  = 0;
  theScanInfo        	= 0;
  theTotalNrOfKeyWordInSignal = 8;
  theMagicNumber        = 0xABCDEF01;
  theBlobList = NULL;
  m_abortOption = -1;
  m_no_disk_flag = 1;

  tSignal = theNdb->getSignal();
  if (tSignal == NULL)
  {
    setErrorCode(4000);
    return -1;
  }
  theTCREQ = tSignal;
  theTCREQ->setSignal(m_tcReqGSN);

  theAI_LenInCurrAI = 20;
  TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
  tcKeyReq->scanInfo = 0;
  theKEYINFOptr = &tcKeyReq->keyInfo[0];
  theATTRINFOptr = &tcKeyReq->attrInfo[0];
  theReceiver.init(NdbReceiver::NDB_OPERATION, this);
  return 0;
}

/******************************************************************************
 * void release();
 *
 * Remark:        Release all objects connected to the operation object.
 *****************************************************************************/
void
NdbOperation::release()
{
  NdbApiSignal* tSignal;
  NdbApiSignal* tSaveSignal;
  NdbBranch*	tBranch;
  NdbBranch*	tSaveBranch;
  NdbLabel*	tLabel;
  NdbLabel*	tSaveLabel;
  NdbCall*	tCall;
  NdbCall*	tSaveCall;
  NdbSubroutine* tSubroutine;
  NdbSubroutine* tSaveSubroutine;
  NdbBlob* tBlob;
  NdbBlob* tSaveBlob;

  tSignal = theTCREQ;
  while (tSignal != NULL)
  {
    tSaveSignal = tSignal;
    tSignal = tSignal->next();
    theNdb->releaseSignal(tSaveSignal);
  }
  theTCREQ = NULL;
  theLastKEYINFO = NULL;

  tSignal = theFirstATTRINFO;
  while (tSignal != NULL)
  {
    tSaveSignal = tSignal;
    tSignal = tSignal->next();
    theNdb->releaseSignal(tSaveSignal);
  }
  theFirstATTRINFO = NULL;
  theCurrentATTRINFO = NULL;

  if (theInterpretIndicator == 1)
  {
    tBranch = theFirstBranch;
    while (tBranch != NULL)
    {
      tSaveBranch = tBranch;
      tBranch = tBranch->theNext;
      theNdb->releaseNdbBranch(tSaveBranch);
    }
    tLabel = theFirstLabel;
    while (tLabel != NULL)
    {
      tSaveLabel = tLabel;
      tLabel = tLabel->theNext;
      theNdb->releaseNdbLabel(tSaveLabel);
    }
    tCall = theFirstCall;
    while (tCall != NULL)
    {
      tSaveCall = tCall;
      tCall = tCall->theNext;
      theNdb->releaseNdbCall(tSaveCall);
    }
    tSubroutine = theFirstSubroutine;
    while (tSubroutine != NULL)
    {
      tSaveSubroutine = tSubroutine;
      tSubroutine = tSubroutine->theNext;
      theNdb->releaseNdbSubroutine(tSaveSubroutine);
    }
  }
  tBlob = theBlobList;
  while (tBlob != NULL)
  {
    tSaveBlob = tBlob;
    tBlob = tBlob->theNext;
    theNdb->releaseNdbBlob(tSaveBlob);
  }
  theBlobList = NULL;
  theReceiver.release();
}

NdbRecAttr*
NdbOperation::getValue(const char* anAttrName, char* aValue)
{
  return getValue_impl(m_currentTable->getColumn(anAttrName), aValue);
}

NdbRecAttr*
NdbOperation::getValue(Uint32 anAttrId, char* aValue)
{
  return getValue_impl(m_currentTable->getColumn(anAttrId), aValue);
}

NdbRecAttr*
NdbOperation::getValue(const NdbDictionary::Column* col, char* aValue)
{
  return getValue_impl(&NdbColumnImpl::getImpl(*col), aValue);
}

int
NdbOperation::equal(const char* anAttrName, const char* aValuePassed)
{
  return equal_impl(m_accessTable->getColumn(anAttrName), aValuePassed);
}

int
NdbOperation::equal(Uint32 anAttrId, const char* aValuePassed)
{
  return equal_impl(m_accessTable->getColumn(anAttrId), aValuePassed);
}

int
NdbOperation::setValue(const char* anAttrName, const char* aValuePassed)
{
  return setValue(m_currentTable->getColumn(anAttrName), aValuePassed);
}

int
NdbOperation::setValue(Uint32 anAttrId, const char* aValuePassed)
{
  return setValue(m_currentTable->getColumn(anAttrId), aValuePassed);
}

NdbBlob*
NdbOperation::getBlobHandle(const char* anAttrName)
{
  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrName);
  if (col == NULL)
  {
    setErrorCode(4004);
    return NULL;
  }
  else
  {
    return getBlobHandle(theNdbCon, col);
  }
}

NdbBlob*
NdbOperation::getBlobHandle(Uint32 anAttrId)
{
  const NdbColumnImpl* col = m_currentTable->getColumn(anAttrId);
  if (col == NULL)
  {
    setErrorCode(4004);
    return NULL;
  }
  else
  {
    return getBlobHandle(theNdbCon, col);
  }
}

int
NdbOperation::incValue(const char* anAttrName, Uint32 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::incValue(const char* anAttrName, Uint64 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::incValue(Uint32 anAttrId, Uint32 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::incValue(Uint32 anAttrId, Uint64 aValue)
{
  return incValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::subValue( const char* anAttrName, Uint32 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::subValue( const char* anAttrName, Uint64 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrName), aValue);
}

int
NdbOperation::subValue(Uint32 anAttrId, Uint32 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::subValue(Uint32 anAttrId, Uint64 aValue)
{
  return subValue(m_currentTable->getColumn(anAttrId), aValue);
}

int
NdbOperation::read_attr(const char* anAttrName, Uint32 RegDest)
{
  return read_attr(m_currentTable->getColumn(anAttrName), RegDest);
}

int
NdbOperation::read_attr(Uint32 anAttrId, Uint32 RegDest)
{
  return read_attr(m_currentTable->getColumn(anAttrId), RegDest);
}

int
NdbOperation::write_attr(const char* anAttrName, Uint32 RegDest)
{
  return write_attr(m_currentTable->getColumn(anAttrName), RegDest);
}

int
NdbOperation::write_attr(Uint32 anAttrId, Uint32 RegDest)
{
  return write_attr(m_currentTable->getColumn(anAttrId), RegDest);
}

const char*
NdbOperation::getTableName() const
{
  return m_currentTable->m_externalName.c_str();
}

const NdbDictionary::Table*
NdbOperation::getTable() const
{
  return m_currentTable;
}
<|endoftext|>


<commit_before>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "jstreamsconfig.h"
#include "interface.h"
#include "indexreader.h"
#include "combinedindexmanager.h"
#include "indexwriter.h"
#include "indexscheduler.h"
#include "eventlistener.h"
#include "streamindexer.h"
#include "indexable.h"
#include "indexerconfiguration.h"
#include "stringreader.h"
#include "query.h"
#include "indexerconfiguration.h"
#include <sstream>
#include <vector>
using namespace std;
using namespace jstreams;

Interface::Interface(CombinedIndexManager& m, IndexScheduler& s)
        :manager(m), scheduler(s) {
    eventListener = NULL;
}
void
Interface::setEventListener (EventListener* eListener) {
    eventListener = eListener;
}
int
Interface::countHits(const string& query) {
    Query q(query, -1, 0);
    int count = manager.getIndexReader()->countHits(q);
    return count;
}
ClientInterface::Hits
Interface::getHits(const string& query, int max, int off) {
    Query q(query, max, off);
    Hits hits;
    hits.hits = manager.getIndexReader()->query(q);
    // highlight the hits in the results
    vector<IndexedDocument>::iterator i;
    for (i = hits.hits.begin(); i != hits.hits.end(); ++i) {
        i->fragment = q.highlight(i->fragment);
    }
    return hits;
}
std::vector<std::string>
Interface::getBackEnds() {
    return manager.getBackEnds();
}
map<string, string>
Interface::getStatus() {
    map<string,string> status;
    status["Status"]=scheduler.getStateString();
    ostringstream out;
    out << scheduler.getQueueSize();
    status["Documents in queue"]= out.str();
    out.str("");
    IndexReader* reader = manager.getIndexReader();
    out << reader->countDocuments();
    status["Documents indexed"]= out.str();
    out.str("");
    out << reader->countWords();
    status["Unique words indexed"] = out.str();
    out.str("");
    out << reader->getIndexSize()/1024/1024;
    status["Index size"] = out.str()+" MB";
    return status;
}
string
Interface::stopDaemon() {
    active = false;
    scheduler.stop();
    return "";
}
string
Interface::startIndexing() {
    scheduler.startIndexing();
    return "";
}
string
Interface::stopIndexing() {
    scheduler.stopIndexing();
    return "";
}
set<string>
Interface::getIndexedDirectories() {
    return scheduler.getIndexedDirectories();
}
string
Interface::setIndexedDirectories(set<string> dirs) {
    if (eventListener != NULL)
        eventListener->setIndexedDirectories( dirs);

    scheduler.setIndexedDirectories(dirs);
    return "";
}
void
Interface::setFilters(const std::vector<std::pair<bool,std::string> >& rules) {
    scheduler.getIndexerConfiguration().setFilters(rules);
}
vector<pair<bool,string> >
Interface::getFilters() {
    return scheduler.getIndexerConfiguration().getFilters();
}
set<string>
Interface::getIndexedFiles() {
    map<string, time_t> indexedfiles = manager.getIndexReader()->getFiles(0);
    set<string> r;

    for (map<string, time_t>::iterator iter = indexedfiles.begin(); iter != indexedfiles.end(); iter++)
        r.insert (iter->first);

    return r;
}
void
Interface::indexFile(const std::string &path, uint64_t mtime,
        const std::vector<char>& content) {
    // TODO if the file is already there, remove it first
    IndexWriter* writer = manager.getIndexWriter();
    vector<string> paths;
    paths.push_back(path);
    writer->deleteEntries(paths);
    IndexerConfiguration ic;
    StreamIndexer streamindexer(*writer, ic);
    StringReader<char> sr(&content[0], content.size(), false);
    Indexable idx(path, mtime, *writer, streamindexer);
    idx.index(sr);
}
<commit_msg>Enable shutting down of the daemon over dbus.<commit_after>/* This file is part of Strigi Desktop Search
 *
 * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include "jstreamsconfig.h"
#include "interface.h"
#include "indexreader.h"
#include "combinedindexmanager.h"
#include "indexwriter.h"
#include "indexscheduler.h"
#include "eventlistener.h"
#include "streamindexer.h"
#include "indexable.h"
#include "indexerconfiguration.h"
#include "stringreader.h"
#include "query.h"
#include "indexerconfiguration.h"
#include <sstream>
#include <vector>
#include <sys/types.h>
#include <signal.h>
using namespace std;
using namespace jstreams;

Interface::Interface(CombinedIndexManager& m, IndexScheduler& s)
        :manager(m), scheduler(s) {
    eventListener = NULL;
}
void
Interface::setEventListener (EventListener* eListener) {
    eventListener = eListener;
}
int
Interface::countHits(const string& query) {
    Query q(query, -1, 0);
    int count = manager.getIndexReader()->countHits(q);
    return count;
}
ClientInterface::Hits
Interface::getHits(const string& query, int max, int off) {
    Query q(query, max, off);
    Hits hits;
    hits.hits = manager.getIndexReader()->query(q);
    // highlight the hits in the results
    vector<IndexedDocument>::iterator i;
    for (i = hits.hits.begin(); i != hits.hits.end(); ++i) {
        i->fragment = q.highlight(i->fragment);
    }
    return hits;
}
std::vector<std::string>
Interface::getBackEnds() {
    return manager.getBackEnds();
}
map<string, string>
Interface::getStatus() {
    map<string,string> status;
    status["Status"]=scheduler.getStateString();
    ostringstream out;
    out << scheduler.getQueueSize();
    status["Documents in queue"]= out.str();
    out.str("");
    IndexReader* reader = manager.getIndexReader();
    out << reader->countDocuments();
    status["Documents indexed"]= out.str();
    out.str("");
    out << reader->countWords();
    status["Unique words indexed"] = out.str();
    out.str("");
    out << reader->getIndexSize()/1024/1024;
    status["Index size"] = out.str()+" MB";
    return status;
}
string
Interface::stopDaemon() {
    active = false;
    kill(getpid(), SIGINT);
    return "";
}
string
Interface::startIndexing() {
    scheduler.startIndexing();
    return "";
}
string
Interface::stopIndexing() {
    scheduler.stopIndexing();
    return "";
}
set<string>
Interface::getIndexedDirectories() {
    return scheduler.getIndexedDirectories();
}
string
Interface::setIndexedDirectories(set<string> dirs) {
    if (eventListener != NULL)
        eventListener->setIndexedDirectories( dirs);

    scheduler.setIndexedDirectories(dirs);
    return "";
}
void
Interface::setFilters(const std::vector<std::pair<bool,std::string> >& rules) {
    scheduler.getIndexerConfiguration().setFilters(rules);
}
vector<pair<bool,string> >
Interface::getFilters() {
    return scheduler.getIndexerConfiguration().getFilters();
}
set<string>
Interface::getIndexedFiles() {
    map<string, time_t> indexedfiles = manager.getIndexReader()->getFiles(0);
    set<string> r;

    for (map<string, time_t>::iterator iter = indexedfiles.begin(); iter != indexedfiles.end(); iter++)
        r.insert (iter->first);

    return r;
}
void
Interface::indexFile(const std::string &path, uint64_t mtime,
        const std::vector<char>& content) {
    // TODO if the file is already there, remove it first
    IndexWriter* writer = manager.getIndexWriter();
    vector<string> paths;
    paths.push_back(path);
    writer->deleteEntries(paths);
    IndexerConfiguration ic;
    StreamIndexer streamindexer(*writer, ic);
    StringReader<char> sr(&content[0], content.size(), false);
    Indexable idx(path, mtime, *writer, streamindexer);
    idx.index(sr);
}
<|endoftext|>


<commit_before>/**
@file System/Context.hpp
@brief Context class.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SYSTEM_CONTEXT_HPP_
#define HORD_SYSTEM_CONTEXT_HPP_

#include <Hord/config.hpp>
#include <Hord/aux.hpp>
#include <Hord/Hive/Defs.hpp>
#include <Hord/Hive/Unit.hpp>
#include <Hord/IO/Datastore.hpp>
#include <Hord/Cmd/Defs.hpp>
#include <Hord/Cmd/Unit.hpp>
#include <Hord/Cmd/Stage.hpp>
#include <Hord/System/Driver.hpp>

#include <utility>

namespace Hord {
namespace System {

// Forward declarations
class Context;

/**
	@addtogroup system
	@{
*/

/**
	%Context.

	@warning The context requires the attached datastore and hive
	exist as long as the context exists.

	@remarks This class mediates the behavior of commands one layer
	above the command transmission protocol for a server or client.
*/
class Context final {
public:
	/**
		%Context type.
	*/
	enum class Type : unsigned {
		/**
			Host view.
		*/
		host,

		/**
			Client view.
		*/
		client
	};

	/** Command map. */
	using command_map_type = aux::unordered_map<
		Cmd::IDValue,
		Cmd::UnitUPtr
	>;

	/** Command input deque. */
	using input_deque_type = aux::deque<
		Cmd::StageUPtr
	>;

	/**
		%Stage output destinations.
	*/
	enum class Dest : unsigned {
		/** Output to remote endpoint. */
		remote = 1u,
		/** Output to all other endpoints (local initiation). */
		broadcast_local,
		/** Output to all other endpoints (remote initiation). */
		broadcast_remote,
	};

	/**
		Command output.
	*/
	struct Output {
		/** Destination of stage. */
		Context::Dest dest;
		/** %Stage. */
		Cmd::StageUPtr stage;

		/**
			Constructor with destination and stage.
		*/
		Output(
			Context::Dest const dest,
			Cmd::StageUPtr&& stage
		) noexcept
			: dest(dest)
			, stage(std::move(stage))
		{}
	};

	/** Command output deque. */
	using output_deque_type = aux::deque<
		Context::Output
	>;

	/**
		%Stage execution result.
	*/
	struct Result {
		/** Canonical stage %ID. */
		Cmd::ID id;
		/** Command status. */
		Cmd::Status status;
		/** Command unit. */
		Cmd::UnitUPtr command;
	};

private:
	Type const m_type;
	System::Driver& m_driver;
	IO::Datastore& m_datastore;
	Hive::Unit& m_hive;
	Cmd::IDValue m_genid;

	// NB: Stores initiator stages
	command_map_type m_active;

	// Remote results and local results
	input_deque_type m_input;
	output_deque_type m_output;

	Cmd::IDValue
	next_id() noexcept;

	void
	terminate(
		Result& result,
		Cmd::Stage& input_stage,
		command_map_type::iterator it,
		bool const push_terminator
	) noexcept;

	Context() = delete;
	Context(Context const&) = delete;
	Context& operator=(Context const&) = delete;
	Context& operator=(Context&&) = delete;

	Context(
		Type const type,
		System::Driver& driver,
		System::Driver::datastore_hive_pair& hive_pair
	);

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Context() noexcept;

	/** Move constructor. */
	Context(Context&&) noexcept;

	/**
		Constructor with type, driver, and hive ID.

		@throws Error{ErrorCode::context_invalid_hive}
		If @a hive_id does not exist within @a driver.
	*/
	Context(
		Type const type,
		System::Driver& driver,
		Hive::ID const hive_id
	);
/// @}

/** @name Properties */ /// @{
	/**
		Get type.
	*/
	Type
	get_type() const noexcept {
		return m_type;
	}

	/**
		Get driver.
	*/
	System::Driver&
	get_driver() noexcept {
		return m_driver;
	}

	/**
		Get driver.
	*/
	System::Driver const&
	get_driver() const noexcept {
		return m_driver;
	}

	/**
		Get datastore.
	*/
	IO::Datastore&
	get_datastore() noexcept {
		return m_datastore;
	}

	/**
		Get datastore.
	*/
	IO::Datastore const&
	get_datastore() const noexcept {
		return m_datastore;
	}

	/**
		Get hive (mutable).
	*/
	Hive::Unit&
	get_hive() noexcept {
		return m_hive;
	}

	/**
		Get hive.
	*/
	Hive::Unit const&
	get_hive() const noexcept {
		return m_hive;
	}

	/**
		Get active commands.
	*/
	command_map_type&
	get_active() noexcept {
		return m_active;
	}

	/**
		Get input stages.
	*/
	input_deque_type&
	get_input() noexcept {
		return m_input;
	}

	/**
		Get output stages.
	*/
	output_deque_type&
	get_output() noexcept {
		return m_output;
	}

	/**
		Check if context is a host.
	*/
	bool
	is_host() const noexcept {
		return Context::Type::host == m_type;
	}

	/**
		Check if context is a client.
	*/
	bool
	is_client() const noexcept {
		return Context::Type::client == m_type;
	}

	/**
		Check if stage is local to the context.
	*/
	bool
	is_local(
		Cmd::Stage const& stage
	) const noexcept {
		return is_host()
			? stage.is_host()
			: stage.is_client()
		;
	}

	/**
		Check if stage is remote to the context.
	*/
	bool
	is_remote(
		Cmd::Stage const& stage
	) const noexcept {
		return !is_local(stage);
	}

	/**
		Check if stage is a context-local initiator.
	*/
	bool
	is_local_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_local(stage) && stage.is_initiator();
	}

	/**
		Check if stage is a context-remote initiator.
	*/
	bool
	is_remote_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_remote(stage) && stage.is_initiator();
	}

	/**
		Localize command error status to context.
	*/
	Cmd::Status
	localized_error(
		Cmd::Stage const& stage
	) {
		return is_local(stage)
			? Cmd::Status::error
			: Cmd::Status::error_remote
		;
	}

	/**
		Localize command error status to context.
	*/
	Cmd::Status
	localized_fatal(
		Cmd::Stage const& stage
	) {
		return is_local(stage)
			? Cmd::Status::fatal
			: Cmd::Status::fatal_remote
		;
	}
/// @}

/** @name Operations */ /// @{
	/**
		Initiate command.

		@note This will push and initiate a command as input. The
		command will not be active until the initiator stage is
		executed from execute_input().

		@pre @code
			!command ->is_identified() &&
			!command->has_initiator() &&
			!initiate->is_identified() &&
			initiator->get_command_type() == command->get_type()
		@endcode

		@returns ID of the command.
	*/
	Cmd::ID
	initiate(
		Cmd::UnitUPtr command,
		Cmd::StageUPtr initiator
	) noexcept;

	/**
		Initiate command without making it active locally.

		@note This will push and initiate a command as output. This
		is used for remote broadcasts and, in general, initiator
		stages that don't need to execute anything locally and don't
		require a response from the remote endpoint. It is
		conceptually equivalent to having the stage's execution
		immediately return Cmd::Status::complete (but it is never
		executed; the stage only takes the next local ID and is
		pushed to the remote endpoint).

		@post No active nor done command for the stage on the local
		endpoint.

		@pre @code
			!initiate->is_identified()
		@endcode

		@returns ID of the command.
	*/
	Cmd::ID
	initiate_pass(
		Cmd::StageUPtr initiator
	) noexcept;

	/**
		Push command input.

		@note This is used by userspace to emplace remote stages.

		@pre @code stage->is_identified() @endcode
	*/
	void
	push_input(
		Cmd::StageUPtr stage
	) noexcept;

	/**
		Push stage to remote endpoint.

		@pre @code
			 origin->is_identified() &&
			!stage ->is_identified()
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param initiator Whether the remote endpoint should emplace
		the stage as an initiator (see @c Cmd::ID).
		@param stage %Stage to push.
	*/
	void
	push_remote(
		Cmd::Stage const& origin,
		bool const initiator,
		Cmd::StageUPtr stage
	);

	/**
		Broadcast stage to all other contexts.

		@note @a stage will carry no identity in the output queue.
		Userspace should broadcast a clone of the stage by either
		calling initiate() (when local) or initiate_pass() (when
		remote) on every other context.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains ownership.

		@pre @code
			!stage->is_identified()
		@endcode

		@param stage %Stage to broadcast.
		@param local Whether the stage should be initiated locally
		(or remotely).
	*/
	void
	broadcast(
		Cmd::StageUPtr stage,
		bool const local
	);

	/**
		Execute command on the context.

		@par
		@note Commands are removed (and destroyed) from the active
		group when result status is anything other than
		Cmd::Status::waiting. The result command unit is replaced
		with the command unit that completed execution (with any
		non-waiting status). The command unit shall have the same
		ID and status as @a result.

		@note
		If the stage returns a fatal error or throws an exception,
		the local instance is terminated, existing input and output
		are removed, and GenericTerminate is emitted to the remote,
		which does the same termination, sans GenericTerminate
		emittance.

		@note
		If GenericTerminate is received as input, the result status
		is Cmd::Status::fatal_remote.

		@par
		@note If there are no stages to execute, @a result holds
		@c Cmd::ID_NULL and @c static_cast<Cmd::Status>(0u) (an
		invalid status).

		@throws Error{ErrorCode::context_execute_not_active}
		If a non-initiating input stage carries an inactive %ID.

		@throws Error{ErrorCode::context_execute_already_active}
		If an initiating input stage carries an active %ID.

		@throws ...
		Exception from the stage.

		@returns The number of remaining input stages.
		@param[out] result Execution result.
	*/
	std::size_t
	execute_input(
		Result& result
	);
/// @}
};

/** @} */ // end of doc-group system

} // namespace System
} // namespace Hord

#endif // HORD_SYSTEM_CONTEXT_HPP_
<commit_msg>System::Context: doc: made push briefs clearer; tidy.<commit_after>/**
@file System/Context.hpp
@brief Context class.

@author Timothy Howard
@copyright 2013-2014 Timothy Howard under the MIT license;
see @ref index or the accompanying LICENSE file for full text.
*/

#ifndef HORD_SYSTEM_CONTEXT_HPP_
#define HORD_SYSTEM_CONTEXT_HPP_

#include <Hord/config.hpp>
#include <Hord/aux.hpp>
#include <Hord/Hive/Defs.hpp>
#include <Hord/Hive/Unit.hpp>
#include <Hord/IO/Datastore.hpp>
#include <Hord/Cmd/Defs.hpp>
#include <Hord/Cmd/Unit.hpp>
#include <Hord/Cmd/Stage.hpp>
#include <Hord/System/Driver.hpp>

#include <utility>

namespace Hord {
namespace System {

// Forward declarations
class Context;

/**
	@addtogroup system
	@{
*/

/**
	%Context.

	@warning The context requires the attached datastore and hive
	exist as long as the context exists.

	@remarks This class mediates the behavior of commands one layer
	above the command transmission protocol for a server or client.
*/
class Context final {
public:
	/**
		%Context type.
	*/
	enum class Type : unsigned {
		/**
			Host view.
		*/
		host,

		/**
			Client view.
		*/
		client
	};

	/** Command map. */
	using command_map_type = aux::unordered_map<
		Cmd::IDValue,
		Cmd::UnitUPtr
	>;

	/** Command input deque. */
	using input_deque_type = aux::deque<
		Cmd::StageUPtr
	>;

	/**
		%Stage output destinations.
	*/
	enum class Dest : unsigned {
		/** %Output to remote endpoint. */
		remote = 1u,
		/** %Output to all other endpoints (local initiation). */
		broadcast_local,
		/** %Output to all other endpoints (remote initiation). */
		broadcast_remote,
	};

	/**
		Command output.
	*/
	struct Output {
		/** Destination of stage. */
		Context::Dest dest;
		/** %Stage. */
		Cmd::StageUPtr stage;

		/**
			Constructor with destination and stage.
		*/
		Output(
			Context::Dest const dest,
			Cmd::StageUPtr&& stage
		) noexcept
			: dest(dest)
			, stage(std::move(stage))
		{}
	};

	/** Command output deque. */
	using output_deque_type = aux::deque<
		Context::Output
	>;

	/**
		%Stage execution result.
	*/
	struct Result {
		/** Canonical stage %ID. */
		Cmd::ID id;
		/** Command status. */
		Cmd::Status status;
		/** Command unit. */
		Cmd::UnitUPtr command;
	};

private:
	Type const m_type;
	System::Driver& m_driver;
	IO::Datastore& m_datastore;
	Hive::Unit& m_hive;
	Cmd::IDValue m_genid;

	// NB: Stores initiator stages
	command_map_type m_active;

	// Remote results and local results
	input_deque_type m_input;
	output_deque_type m_output;

	Cmd::IDValue
	next_id() noexcept;

	void
	terminate(
		Result& result,
		Cmd::Stage& input_stage,
		command_map_type::iterator it,
		bool const push_terminator
	) noexcept;

	Context() = delete;
	Context(Context const&) = delete;
	Context& operator=(Context const&) = delete;
	Context& operator=(Context&&) = delete;

	Context(
		Type const type,
		System::Driver& driver,
		System::Driver::datastore_hive_pair& hive_pair
	);

public:
/** @name Special member functions */ /// @{
	/** Destructor. */
	~Context() noexcept;

	/** Move constructor. */
	Context(Context&&) noexcept;

	/**
		Constructor with type, driver, and hive ID.

		@throws Error{ErrorCode::context_invalid_hive}
		If @a hive_id does not exist within @a driver.
	*/
	Context(
		Type const type,
		System::Driver& driver,
		Hive::ID const hive_id
	);
/// @}

/** @name Properties */ /// @{
	/**
		Get type.
	*/
	Type
	get_type() const noexcept {
		return m_type;
	}

	/**
		Get driver.
	*/
	System::Driver&
	get_driver() noexcept {
		return m_driver;
	}

	/**
		Get driver.
	*/
	System::Driver const&
	get_driver() const noexcept {
		return m_driver;
	}

	/**
		Get datastore.
	*/
	IO::Datastore&
	get_datastore() noexcept {
		return m_datastore;
	}

	/**
		Get datastore.
	*/
	IO::Datastore const&
	get_datastore() const noexcept {
		return m_datastore;
	}

	/**
		Get hive (mutable).
	*/
	Hive::Unit&
	get_hive() noexcept {
		return m_hive;
	}

	/**
		Get hive.
	*/
	Hive::Unit const&
	get_hive() const noexcept {
		return m_hive;
	}

	/**
		Get active commands.
	*/
	command_map_type&
	get_active() noexcept {
		return m_active;
	}

	/**
		Get input stages.
	*/
	input_deque_type&
	get_input() noexcept {
		return m_input;
	}

	/**
		Get output stages.
	*/
	output_deque_type&
	get_output() noexcept {
		return m_output;
	}

	/**
		Check if context is a host.
	*/
	bool
	is_host() const noexcept {
		return Context::Type::host == m_type;
	}

	/**
		Check if context is a client.
	*/
	bool
	is_client() const noexcept {
		return Context::Type::client == m_type;
	}

	/**
		Check if stage is local to the context.
	*/
	bool
	is_local(
		Cmd::Stage const& stage
	) const noexcept {
		return is_host()
			? stage.is_host()
			: stage.is_client()
		;
	}

	/**
		Check if stage is remote to the context.
	*/
	bool
	is_remote(
		Cmd::Stage const& stage
	) const noexcept {
		return !is_local(stage);
	}

	/**
		Check if stage is a context-local initiator.
	*/
	bool
	is_local_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_local(stage) && stage.is_initiator();
	}

	/**
		Check if stage is a context-remote initiator.
	*/
	bool
	is_remote_initiator(
		Cmd::Stage const& stage
	) const noexcept {
		return is_remote(stage) && stage.is_initiator();
	}

	/**
		Localize command error status to context.
	*/
	Cmd::Status
	localized_error(
		Cmd::Stage const& stage
	) {
		return is_local(stage)
			? Cmd::Status::error
			: Cmd::Status::error_remote
		;
	}

	/**
		Localize command error status to context.
	*/
	Cmd::Status
	localized_fatal(
		Cmd::Stage const& stage
	) {
		return is_local(stage)
			? Cmd::Status::fatal
			: Cmd::Status::fatal_remote
		;
	}
/// @}

/** @name Operations */ /// @{
	/**
		Initiate command.

		@note This will push and initiate a command as input. The
		command will not be active until the initiator stage is
		executed from execute_input().

		@pre @code
			!command ->is_identified() &&
			!command->has_initiator() &&
			!initiate->is_identified() &&
			initiator->get_command_type() == command->get_type()
		@endcode

		@returns ID of the command.
	*/
	Cmd::ID
	initiate(
		Cmd::UnitUPtr command,
		Cmd::StageUPtr initiator
	) noexcept;

	/**
		Initiate command without making it active locally.

		@note This will push and initiate a command as output. This
		is used for remote broadcasts and, in general, initiator
		stages that don't need to execute anything locally and don't
		require a response from the remote endpoint. It is
		conceptually equivalent to having the stage's execution
		immediately return Cmd::Status::complete (but it is never
		executed; the stage only takes the next local ID and is
		pushed to the remote endpoint).

		@post No active command for the stage on the local endpoint.

		@pre @code
			!initiate->is_identified()
		@endcode

		@returns ID of the command.
	*/
	Cmd::ID
	initiate_pass(
		Cmd::StageUPtr initiator
	) noexcept;

	/**
		Push stage as input from remote endpoint.

		@note This is used by userspace to emplace remote stages.

		@pre @code stage->is_identified() @endcode
	*/
	void
	push_input(
		Cmd::StageUPtr stage
	) noexcept;

	/**
		Push stage as output to remote endpoint.

		@pre @code
			 origin->is_identified() &&
			!stage ->is_identified()
		@endcode

		@throws Error{ErrorCode::context_output_detached}
		If @a origin is not part of an active command.

		@param origin Origin stage.
		@param initiator Whether the remote endpoint should emplace
		the stage as an initiator (see @c Cmd::ID).
		@param stage %Stage to push.
	*/
	void
	push_remote(
		Cmd::Stage const& origin,
		bool const initiator,
		Cmd::StageUPtr stage
	);

	/**
		Push stage as broadcast output.

		@note @a stage will carry no identity in the output queue.
		Userspace should broadcast a clone of the stage by either
		calling initiate() (when local) or initiate_pass() (when
		remote) on every other context.

		@par
		@note If @a stage is pushed, the context takes ownership
		(@a stage is moved). Otherwise, the callee retains ownership.

		@pre @code
			!stage->is_identified()
		@endcode

		@param stage %Stage to broadcast.
		@param local Whether the stage should be initiated locally
		(or remotely).
	*/
	void
	broadcast(
		Cmd::StageUPtr stage,
		bool const local
	);

	/**
		Execute command on the context.

		@par
		@note Commands are removed from the active group when result
		status is anything other than Cmd::Status::waiting. The
		result command unit is replaced with the command unit that
		completed execution (with any non-waiting status). The
		command unit shall have the same ID and status as @a result.

		@note
		If the stage returns a fatal error or throws an exception,
		the local instance is terminated, existing input and output
		are removed, and GenericTerminate is emitted to the remote,
		which does the same termination, sans GenericTerminate
		emittance.

		@note
		If GenericTerminate is received as input, the result status
		is Cmd::Status::fatal_remote.

		@par
		@note If there are no stages to execute, @a result holds
		@c Cmd::ID_NULL and @c static_cast<Cmd::Status>(0u) (an
		invalid status).

		@throws Error{ErrorCode::context_execute_not_active}
		If a non-initiating input stage carries an inactive %ID.

		@throws Error{ErrorCode::context_execute_already_active}
		If an initiating input stage carries an active %ID.

		@throws ...
		Exception from the stage.

		@returns The number of remaining input stages.
		@param[out] result Execution result.
	*/
	std::size_t
	execute_input(
		Result& result
	);
/// @}
};

/** @} */ // end of doc-group system

} // namespace System
} // namespace Hord

#endif // HORD_SYSTEM_CONTEXT_HPP_
<|endoftext|>


<commit_before>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "heritage.hh"
#include "widget.hh"

namespace Rapicorn {

static Color
adjust_color (Color  color,
              double saturation_factor,
              double value_factor)
{
  double hue, saturation, value;
  color.get_hsv (&hue, &saturation, &value);
  saturation *= saturation_factor;
  value *= value_factor;
  color.set_hsv (hue, MIN (1, saturation), MIN (1, value));
  return color;
}

static Color lighten (Color color) { return adjust_color (color, 1.0, 1.1); }
static Color darken  (Color color) { return adjust_color (color, 1.0, 0.9); }

static Color
state_color (Color     color,
             StateType state,
             ColorType ctype)
{
  /* foreground colors remain stable across certain states */
  bool background_color = true;
  switch (ctype)
    {
    case COLOR_FOREGROUND: case COLOR_FOCUS:
    case COLOR_BLACK:      case COLOR_WHITE:
    case COLOR_RED:        case COLOR_YELLOW:
    case COLOR_GREEN:      case COLOR_CYAN:
    case COLOR_BLUE:       case COLOR_MAGENTA:
      background_color = false;
    default: ;
    }
  Color c = color;
  if (state & STATE_IMPRESSED && background_color)
    c = adjust_color (c, 1.0, 0.8);
  if (state & STATE_INSENSITIVE)
    c = adjust_color (c, 0.8, 1.075);
  if (state & STATE_PRELIGHT && background_color &&
      !(state & STATE_INSENSITIVE))     /* ignore prelight if insensitive */
    c = adjust_color (c, 1.2, 1.0);
  return c;
}

static Color
colorset_normal (StateType state,
                 ColorType color_type)
{
  switch (color_type)
    {
    default:
    case COLOR_NONE:            return 0x00000000;
    case COLOR_FOREGROUND:      return 0xff000000;
    case COLOR_BACKGROUND:      return 0xffdfdcd8;
    case COLOR_BACKGROUND_EVEN: return lighten (colorset_normal (state, COLOR_BACKGROUND));
    case COLOR_BACKGROUND_ODD:  return darken  (colorset_normal (state, COLOR_BACKGROUND));
    case COLOR_DARK:            return 0xff9f9c98;
    case COLOR_DARK_SHADOW:     return adjust_color (colorset_normal (state, COLOR_DARK), 1, 0.9); // 0xff8f8c88
    case COLOR_DARK_GLINT:      return adjust_color (colorset_normal (state, COLOR_DARK), 1, 1.1); // 0xffafaca8
    case COLOR_LIGHT:           return 0xffdfdcd8;
    case COLOR_LIGHT_SHADOW:    return adjust_color (colorset_normal (state, COLOR_LIGHT), 1, 0.93); // 0xffcfccc8
    case COLOR_LIGHT_GLINT:     return adjust_color (colorset_normal (state, COLOR_LIGHT), 1, 1.07); // 0xffefece8
    case COLOR_FOCUS:           return 0xff000060;
    case COLOR_BLACK:           return 0xff000000;
    case COLOR_WHITE:           return 0xffffffff;
    case COLOR_RED:             return 0xffff0000;
    case COLOR_YELLOW:          return 0xffffff00;
    case COLOR_GREEN:           return 0xff00ff00;
    case COLOR_CYAN:            return 0xff00ffff;
    case COLOR_BLUE:            return 0xff0000ff;
    case COLOR_MAGENTA:         return 0xffff00ff;
    }
}

static Color
colorset_selected (StateType state,
                   ColorType color_type)
{
  switch (color_type)
    {
    case COLOR_FOREGROUND:      return 0xffeeeeee;
    case COLOR_BACKGROUND:      return 0xff111188;
    case COLOR_BACKGROUND_EVEN: return lighten (colorset_selected (state, COLOR_BACKGROUND));
    case COLOR_BACKGROUND_ODD:  return darken  (colorset_selected (state, COLOR_BACKGROUND));
    default:                    return colorset_normal (state, color_type);
    }
}

static Color
colorset_base (StateType state,
               ColorType color_type)
{
  switch (color_type)
    {
    case COLOR_FOREGROUND:      return 0xff101010;
    case COLOR_BACKGROUND:      return 0xfff4f4f4;
    case COLOR_BACKGROUND_EVEN: return lighten (colorset_base (state, COLOR_BACKGROUND));
    case COLOR_BACKGROUND_ODD:  return darken  (colorset_base (state, COLOR_BACKGROUND));
    default:                    return colorset_normal (state, color_type);
    }
}

typedef Color (*ColorFunc) (StateType, ColorType);

class Heritage::Internals {
  WidgetImpl &widget_;
  ColorFunc ncf, scf;
public:
  Heritage *selected;
  Internals (WidgetImpl &widget,
             ColorFunc normal_cf,
             ColorFunc selected_cf) :
    widget_ (widget), ncf (normal_cf), scf (selected_cf), selected (NULL)
  {}
  bool
  match (WidgetImpl &widget,
         ColorFunc normal_cf,
         ColorFunc selected_cf)
  {
    return widget == widget_ && normal_cf == ncf && selected_cf == scf;
  }
  Color
  get_color (const Heritage *heritage,
             StateType       state,
             ColorType       ct) const
  {
    if (heritage == selected)
      return scf (state, ct);
    else
      return ncf (state, ct);
  }
};

Heritage::~Heritage ()
{
  if (internals_)
    {
      if (internals_->selected == this)
        internals_->selected = NULL;
      else
        {
          if (internals_->selected)
            internals_->selected->internals_ = NULL;
          delete internals_;
          internals_ = NULL;
        }
    }
}

Heritage*
Heritage::create_heritage (WindowImpl     &window,
                           WidgetImpl       &widget,
                           ColorSchemeType color_scheme)
{
  WindowImpl *iwindow = widget.get_window();
  assert (iwindow == &window);
  ColorFunc cnorm = colorset_normal, csel = colorset_selected;
  switch (color_scheme)
    {
    case COLOR_BASE:            cnorm = colorset_base; break;
    case COLOR_SELECTED:        cnorm = colorset_selected; break;
    case COLOR_NORMAL: case COLOR_INHERIT: ;
    }
  Internals *internals = new Internals (widget, cnorm, csel);
  Heritage *self = new Heritage (window, internals);
  return self;
}

Heritage*
Heritage::adapt_heritage (WidgetImpl       &widget,
                          ColorSchemeType color_scheme)
{
  if (internals_)
    {
      ColorFunc cnorm = colorset_normal, csel = colorset_selected;
      switch (color_scheme)
        {
        case COLOR_INHERIT:     return this;
        case COLOR_BASE:        cnorm = colorset_base; break;
        case COLOR_SELECTED:    cnorm = colorset_selected; break;
        case COLOR_NORMAL:      ;
        }
      if (internals_->match (widget, cnorm, csel))
        return this;
    }
  WindowImpl *window = widget.get_window();
  if (!window)
    fatal ("Heritage: create heritage without window widget for: %s", widget.name().c_str());
  return create_heritage (*window, widget, color_scheme);
}

Heritage::Heritage (WindowImpl &window,
                    Internals  *internals) :
  internals_ (internals), window_ (window)
{}

Heritage&
Heritage::selected ()
{
  if (internals_)
    {
      if (!internals_->selected)
        {
          internals_->selected = new Heritage (window_, internals_);
          ref_sink (internals_->selected);
        }
      return *internals_->selected;
    }
  else
    return *this;
}

Color
Heritage::get_color (StateType state,
                     ColorType color_type) const
{
  Color c;
  if (internals_)
    c = internals_->get_color (this, state, color_type);
  return state_color (c, state, color_type);
}

Color
Heritage::insensitive_ink (StateType state,
                           Color    *glintp) const
{
  /* constrcut insensitive ink from a mixture of foreground and dark_color */
  Color ink = get_color (state, COLOR_FOREGROUND);
  ink.combine (get_color (state, COLOR_DARK), 0x80);
  Color glint = get_color (state, COLOR_LIGHT);
  if (glintp)
    *glintp = glint;
  return ink;
}

Color
Heritage::resolve_color (const String  &color_name,
                         StateType      state,
                         ColorType      color_type)
{
  Aida::EnumInfo ect = Aida::enum_info<ColorType>();
  if (color_name[0] == '#')
    {
      uint32 argb = string_to_int (&color_name[1], 16);
      Color c (argb);
      /* invert alpha (transparency -> opacity) */
      c.alpha (0xff - c.alpha());
      return state_color (c, state, color_type);
    }
  const Aida::EnumInfo::Value *value = ect.find_first (color_name);
  if (value)
    return get_color (state, ColorType (value->value));
  else
    {
      Color parsed_color = Color::from_name (color_name);
      if (!parsed_color) // transparent black
        return get_color (state, color_type);
      else
        return state_color (parsed_color, state, color_type);
    }
}

} // Rapicorn
<commit_msg>UI: use brighter colors for list row even/odd coloring and selection<commit_after>// Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
#include "heritage.hh"
#include "widget.hh"

namespace Rapicorn {

static Color
adjust_color (Color  color,
              double saturation_factor,
              double value_factor)
{
  double hue, saturation, value;
  color.get_hsv (&hue, &saturation, &value);
  saturation *= saturation_factor;
  value *= value_factor;
  color.set_hsv (hue, MIN (1, saturation), MIN (1, value));
  return color;
}

static Color lighten   (Color color) { return adjust_color (color, 1.0, 1.1); }
static Color darken    (Color color) { return adjust_color (color, 1.0, 0.9); }
static Color alternate (Color color) { return adjust_color (color, 1.0, 0.98); } // tainting for even-odd alterations

static Color
state_color (Color     color,
             StateType state,
             ColorType ctype)
{
  /* foreground colors remain stable across certain states */
  bool background_color = true;
  switch (ctype)
    {
    case COLOR_FOREGROUND: case COLOR_FOCUS:
    case COLOR_BLACK:      case COLOR_WHITE:
    case COLOR_RED:        case COLOR_YELLOW:
    case COLOR_GREEN:      case COLOR_CYAN:
    case COLOR_BLUE:       case COLOR_MAGENTA:
      background_color = false;
    default: ;
    }
  Color c = color;
  if (state & STATE_IMPRESSED && background_color)
    c = adjust_color (c, 1.0, 0.8);
  if (state & STATE_INSENSITIVE)
    c = adjust_color (c, 0.8, 1.075);
  if (state & STATE_PRELIGHT && background_color &&
      !(state & STATE_INSENSITIVE))     /* ignore prelight if insensitive */
    c = adjust_color (c, 1.2, 1.0);
  return c;
}

static Color
colorset_normal (StateType state,
                 ColorType color_type)
{
  switch (color_type)
    {
    default:
    case COLOR_NONE:            return 0x00000000;
    case COLOR_FOREGROUND:      return 0xff000000;
    case COLOR_BACKGROUND:      return 0xffdfdcd8;
    case COLOR_BACKGROUND_EVEN: return colorset_normal (state, COLOR_BACKGROUND);
    case COLOR_BACKGROUND_ODD:  return alternate (colorset_normal (state, COLOR_BACKGROUND));
    case COLOR_DARK:            return 0xff9f9c98;
    case COLOR_DARK_SHADOW:     return adjust_color (colorset_normal (state, COLOR_DARK), 1, 0.9); // 0xff8f8c88
    case COLOR_DARK_GLINT:      return adjust_color (colorset_normal (state, COLOR_DARK), 1, 1.1); // 0xffafaca8
    case COLOR_LIGHT:           return 0xffdfdcd8;
    case COLOR_LIGHT_SHADOW:    return adjust_color (colorset_normal (state, COLOR_LIGHT), 1, 0.93); // 0xffcfccc8
    case COLOR_LIGHT_GLINT:     return adjust_color (colorset_normal (state, COLOR_LIGHT), 1, 1.07); // 0xffefece8
    case COLOR_FOCUS:           return 0xff000060;
    case COLOR_BLACK:           return 0xff000000;
    case COLOR_WHITE:           return 0xffffffff;
    case COLOR_RED:             return 0xffff0000;
    case COLOR_YELLOW:          return 0xffffff00;
    case COLOR_GREEN:           return 0xff00ff00;
    case COLOR_CYAN:            return 0xff00ffff;
    case COLOR_BLUE:            return 0xff0000ff;
    case COLOR_MAGENTA:         return 0xffff00ff;
    }
}

static Color
colorset_selected (StateType state,
                   ColorType color_type)
{
  switch (color_type)
    {
    case COLOR_FOREGROUND:      return 0xfffcfdfe;      // inactive: 0xff010203
    case COLOR_BACKGROUND:      return 0xff2595e5;      // inactive: 0xff33aaff
    case COLOR_BACKGROUND_EVEN: return colorset_selected (state, COLOR_BACKGROUND);
    case COLOR_BACKGROUND_ODD:  return alternate (colorset_selected (state, COLOR_BACKGROUND));
    default:                    return colorset_normal (state, color_type);
    }
}

static Color
colorset_base (StateType state,
               ColorType color_type)
{
  switch (color_type)
    {
    case COLOR_FOREGROUND:      return 0xff101010;
    case COLOR_BACKGROUND:      return 0xfff4f4f4;
    case COLOR_BACKGROUND_EVEN: return colorset_base (state, COLOR_BACKGROUND);
    case COLOR_BACKGROUND_ODD:  return alternate (colorset_base (state, COLOR_BACKGROUND));
    default:                    return colorset_normal (state, color_type);
    }
}

typedef Color (*ColorFunc) (StateType, ColorType);

class Heritage::Internals {
  WidgetImpl &widget_;
  ColorFunc ncf, scf;
public:
  Heritage *selected;
  Internals (WidgetImpl &widget,
             ColorFunc normal_cf,
             ColorFunc selected_cf) :
    widget_ (widget), ncf (normal_cf), scf (selected_cf), selected (NULL)
  {}
  bool
  match (WidgetImpl &widget,
         ColorFunc normal_cf,
         ColorFunc selected_cf)
  {
    return widget == widget_ && normal_cf == ncf && selected_cf == scf;
  }
  Color
  get_color (const Heritage *heritage,
             StateType       state,
             ColorType       ct) const
  {
    if (heritage == selected)
      return scf (state, ct);
    else
      return ncf (state, ct);
  }
};

Heritage::~Heritage ()
{
  if (internals_)
    {
      if (internals_->selected == this)
        internals_->selected = NULL;
      else
        {
          if (internals_->selected)
            internals_->selected->internals_ = NULL;
          delete internals_;
          internals_ = NULL;
        }
    }
}

Heritage*
Heritage::create_heritage (WindowImpl     &window,
                           WidgetImpl       &widget,
                           ColorSchemeType color_scheme)
{
  WindowImpl *iwindow = widget.get_window();
  assert (iwindow == &window);
  ColorFunc cnorm = colorset_normal, csel = colorset_selected;
  switch (color_scheme)
    {
    case COLOR_BASE:            cnorm = colorset_base; break;
    case COLOR_SELECTED:        cnorm = colorset_selected; break;
    case COLOR_NORMAL: case COLOR_INHERIT: ;
    }
  Internals *internals = new Internals (widget, cnorm, csel);
  Heritage *self = new Heritage (window, internals);
  return self;
}

Heritage*
Heritage::adapt_heritage (WidgetImpl       &widget,
                          ColorSchemeType color_scheme)
{
  if (internals_)
    {
      ColorFunc cnorm = colorset_normal, csel = colorset_selected;
      switch (color_scheme)
        {
        case COLOR_INHERIT:     return this;
        case COLOR_BASE:        cnorm = colorset_base; break;
        case COLOR_SELECTED:    cnorm = colorset_selected; break;
        case COLOR_NORMAL:      ;
        }
      if (internals_->match (widget, cnorm, csel))
        return this;
    }
  WindowImpl *window = widget.get_window();
  if (!window)
    fatal ("Heritage: create heritage without window widget for: %s", widget.name().c_str());
  return create_heritage (*window, widget, color_scheme);
}

Heritage::Heritage (WindowImpl &window,
                    Internals  *internals) :
  internals_ (internals), window_ (window)
{}

Heritage&
Heritage::selected ()
{
  if (internals_)
    {
      if (!internals_->selected)
        {
          internals_->selected = new Heritage (window_, internals_);
          ref_sink (internals_->selected);
        }
      return *internals_->selected;
    }
  else
    return *this;
}

Color
Heritage::get_color (StateType state,
                     ColorType color_type) const
{
  Color c;
  if (internals_)
    c = internals_->get_color (this, state, color_type);
  return state_color (c, state, color_type);
}

Color
Heritage::insensitive_ink (StateType state,
                           Color    *glintp) const
{
  /* constrcut insensitive ink from a mixture of foreground and dark_color */
  Color ink = get_color (state, COLOR_FOREGROUND);
  ink.combine (get_color (state, COLOR_DARK), 0x80);
  Color glint = get_color (state, COLOR_LIGHT);
  if (glintp)
    *glintp = glint;
  return ink;
}

Color
Heritage::resolve_color (const String  &color_name,
                         StateType      state,
                         ColorType      color_type)
{
  Aida::EnumInfo ect = Aida::enum_info<ColorType>();
  if (color_name[0] == '#')
    {
      uint32 argb = string_to_int (&color_name[1], 16);
      Color c (argb);
      /* invert alpha (transparency -> opacity) */
      c.alpha (0xff - c.alpha());
      return state_color (c, state, color_type);
    }
  const Aida::EnumInfo::Value *value = ect.find_first (color_name);
  if (value)
    return get_color (state, ColorType (value->value));
  else
    {
      Color parsed_color = Color::from_name (color_name);
      if (!parsed_color) // transparent black
        return get_color (state, color_type);
      else
        return state_color (parsed_color, state, color_type);
    }
}

} // Rapicorn
<|endoftext|>


<commit_before>#pragma once

#include <cilantro/renderables.hpp>
#include <cilantro/point_cloud.hpp>
#include <pangolin/display/display_internal.h>

namespace cilantro {
    class Visualizer {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW

        Visualizer();
        Visualizer(const std::string &window_name, const std::string &display_name);
        ~Visualizer();

        Visualizer& addPointCloud(const std::string &name, const PointCloud &cloud, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloud(const std::string &name, const std::vector<Eigen::Vector3f> &points, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloudColors(const std::string &name, const std::vector<Eigen::Vector3f> &colors);
        Visualizer& addPointCloudValues(const std::string &name, const std::vector<float> &point_values);

        Visualizer& addPointCloudNormals(const std::string &name, const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloudNormals(const std::string &name, const PointCloud &cloud, const RenderingProperties &rp = RenderingProperties());

        Visualizer& addPointCorrespondences(const std::string &name, const std::vector<Eigen::Vector3f> &points_src, const std::vector<Eigen::Vector3f> &points_dst, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCorrespondences(const std::string &name, const PointCloud &cloud_src, const PointCloud &cloud_dst, const RenderingProperties &rp = RenderingProperties());

        Visualizer& addCoordinateSystem(const std::string &name, float scale = 1.0f, const Eigen::Matrix4f &tf = Eigen::Matrix4f::Identity(), const RenderingProperties &rp = RenderingProperties());

        Visualizer& addTriangleMesh(const std::string &name, const PointCloud &cloud, const std::vector<std::vector<size_t> > &faces, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addTriangleMesh(const std::string &name, const std::vector<Eigen::Vector3f> &vertices, const std::vector<std::vector<size_t> > &faces, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addTriangleMeshVertexNormals(const std::string &name, const std::vector<Eigen::Vector3f> &vertex_normals);
        Visualizer& addTriangleMeshFaceNormals(const std::string &name, const std::vector<Eigen::Vector3f> &face_normals);
        Visualizer& addTriangleMeshVertexColors(const std::string &name, const std::vector<Eigen::Vector3f> &vertex_colors);
        Visualizer& addTriangleMeshFaceColors(const std::string &name, const std::vector<Eigen::Vector3f> &face_colors);
        Visualizer& addTriangleMeshVertexValues(const std::string &name, const std::vector<float> &vertex_values);
        Visualizer& addTriangleMeshFaceValues(const std::string &name, const std::vector<float> &face_values);

        inline Visualizer& clear() { renderables_.clear(); return *this; }
        inline Visualizer& remove(const std::string &name) { renderables_.erase(name); return *this; }

        Visualizer& clearRenderArea();
        Visualizer& render();
        inline Visualizer& finishFrame() { gl_context_->MakeCurrent(); pangolin::FinishFrame(); return *this; }
        inline Visualizer& spinOnce() { clearRenderArea(); render(); finishFrame(); return *this; }

        inline bool wasStopped() const { return gl_context_->quit; }

        bool getVisibilityStatus(const std::string &name) const;
        Visualizer& setVisibilityStatus(const std::string &name, bool visible);
        inline Visualizer& toggleVisibilityStatus(const std::string &name) { setVisibilityStatus(name, !getVisibilityStatus(name)); return *this; }

        RenderingProperties getRenderingProperties(const std::string &name) const;
        Visualizer& setRenderingProperties(const std::string &name, const RenderingProperties &rp);

        std::vector<std::string> getObjectNames() const;

        inline Eigen::Vector3f getClearColor() const { return clear_color_; }
        inline Visualizer& setClearColor(const Eigen::Vector3f &color) { clear_color_ = color; return *this; }
        inline Visualizer& setClearColor(float r, float g, float b) { clear_color_ = Eigen::Vector3f(r,g,b); return *this; }

        Visualizer& setProjectionMatrix(int w, int h, pangolin::GLprecision fu, pangolin::GLprecision fv, pangolin::GLprecision u0, pangolin::GLprecision v0, pangolin::GLprecision zNear, pangolin::GLprecision zFar);
        Visualizer& setProjectionMatrix(int w, int h, const Eigen::Matrix3f &intrinsics, pangolin::GLprecision zNear, pangolin::GLprecision zFar);

        Eigen::Matrix4f getCameraPose() const;
        Visualizer& getCameraPose(Eigen::Vector3f &position, Eigen::Vector3f &look_at, Eigen::Vector3f &up_direction) const;
        Visualizer& setCameraPose(const Eigen::Vector3f &position, const Eigen::Vector3f &look_at, const Eigen::Vector3f &up_direction);
        Visualizer& setCameraPose(float pos_x, float pos_y, float pos_z, float look_at_x, float look_at_y, float look_at_z, float up_dir_x, float up_dir_y, float up_dir_z);
        Visualizer& setCameraPose(const Eigen::Matrix4f &pose);

        Visualizer& registerKeyboardCallback(const std::vector<int> &keys, std::function<void(Visualizer&,int,void*)> func, void *cookie);

        pangolin::TypedImage getRenderImage(float scale = 1.0f, bool rgba = false);
        Visualizer& saveRenderAsImage(const std::string &file_name, float scale, float quality, bool rgba = false);

        Visualizer& startVideoRecording(const std::string &uri, size_t fps, bool record_on_render = false, float scale = 1.0f, bool rgba = false);
        Visualizer& recordVideoFrame();
        Visualizer& stopVideoRecording();
        inline bool isRecording() const { return !!video_recorder_; }

        inline pangolin::PangolinGl* getPangolinGLContext() const { return gl_context_; }
        inline pangolin::View* getPangolinDisplay() const { return display_; }

        inline pangolin::OpenGlRenderState* getPangolinRenderState() const { return gl_render_state_.get(); }

    private:
        pangolin::PangolinGl *gl_context_;
        pangolin::View *display_;

        std::shared_ptr<pangolin::OpenGlRenderState> gl_render_state_;
        std::shared_ptr<pangolin::Handler3D> input_handler_;
        pangolin::OpenGlMatrix initial_model_view_;
        std::shared_ptr<pangolin::VideoOutput> video_recorder_;
        size_t video_fps_;
        float video_scale_;
        bool video_rgba_;
        bool video_record_on_render_;
        Eigen::Vector3f clear_color_;
        Eigen::Matrix4f cam_axes_rot_;

        std::map<std::string, std::shared_ptr<Renderable> > renderables_;

        void init_(const std::string &window_name, const std::string &display_name);

        static void point_size_callback_(Visualizer &viz, int key);
        static void reset_view_callback_(Visualizer &viz);
        static void wireframe_toggle_callback_(Visualizer &viz);

        struct {
            inline bool operator() (const std::pair<Renderable*, float> &p1, const std::pair<Renderable*, float> &p2) const {
                return std::make_pair(p1.first->renderingProperties.opacity == 1.0f, p1.second) > std::make_pair(p2.first->renderingProperties.opacity == 1.0f, p2.second);
            }
        } render_priority_comparator_;
    };
}
<commit_msg>Visualizer fix update<commit_after>#pragma once

#include <cilantro/renderables.hpp>
#include <cilantro/point_cloud.hpp>
#include <pangolin/display/display_internal.h>

namespace cilantro {
    class Visualizer {
    public:
        EIGEN_MAKE_ALIGNED_OPERATOR_NEW

        Visualizer();
        Visualizer(const std::string &window_name, const std::string &display_name);
        ~Visualizer();

        Visualizer& addPointCloud(const std::string &name, const PointCloud &cloud, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloud(const std::string &name, const std::vector<Eigen::Vector3f> &points, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloudColors(const std::string &name, const std::vector<Eigen::Vector3f> &colors);
        Visualizer& addPointCloudValues(const std::string &name, const std::vector<float> &point_values);

        Visualizer& addPointCloudNormals(const std::string &name, const std::vector<Eigen::Vector3f> &points, const std::vector<Eigen::Vector3f> &normals, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCloudNormals(const std::string &name, const PointCloud &cloud, const RenderingProperties &rp = RenderingProperties());

        Visualizer& addPointCorrespondences(const std::string &name, const std::vector<Eigen::Vector3f> &points_src, const std::vector<Eigen::Vector3f> &points_dst, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addPointCorrespondences(const std::string &name, const PointCloud &cloud_src, const PointCloud &cloud_dst, const RenderingProperties &rp = RenderingProperties());

        Visualizer& addCoordinateSystem(const std::string &name, float scale = 1.0f, const Eigen::Matrix4f &tf = Eigen::Matrix4f::Identity(), const RenderingProperties &rp = RenderingProperties());

        Visualizer& addTriangleMesh(const std::string &name, const PointCloud &cloud, const std::vector<std::vector<size_t> > &faces, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addTriangleMesh(const std::string &name, const std::vector<Eigen::Vector3f> &vertices, const std::vector<std::vector<size_t> > &faces, const RenderingProperties &rp = RenderingProperties());
        Visualizer& addTriangleMeshVertexNormals(const std::string &name, const std::vector<Eigen::Vector3f> &vertex_normals);
        Visualizer& addTriangleMeshFaceNormals(const std::string &name, const std::vector<Eigen::Vector3f> &face_normals);
        Visualizer& addTriangleMeshVertexColors(const std::string &name, const std::vector<Eigen::Vector3f> &vertex_colors);
        Visualizer& addTriangleMeshFaceColors(const std::string &name, const std::vector<Eigen::Vector3f> &face_colors);
        Visualizer& addTriangleMeshVertexValues(const std::string &name, const std::vector<float> &vertex_values);
        Visualizer& addTriangleMeshFaceValues(const std::string &name, const std::vector<float> &face_values);

        inline Visualizer& clear() { renderables_.clear(); return *this; }
        inline Visualizer& remove(const std::string &name) { renderables_.erase(name); return *this; }

        Visualizer& clearRenderArea();
        Visualizer& render();
        inline Visualizer& finishFrame() { gl_context_->MakeCurrent(); pangolin::FinishFrame(); return *this; }
        inline Visualizer& spinOnce() { clearRenderArea(); render(); finishFrame(); return *this; }

        inline bool wasStopped() const { return gl_context_->quit; }

        bool getVisibilityStatus(const std::string &name) const;
        Visualizer& setVisibilityStatus(const std::string &name, bool visible);
        inline Visualizer& toggleVisibilityStatus(const std::string &name) { setVisibilityStatus(name, !getVisibilityStatus(name)); return *this; }

        RenderingProperties getRenderingProperties(const std::string &name) const;
        Visualizer& setRenderingProperties(const std::string &name, const RenderingProperties &rp);

        std::vector<std::string> getObjectNames() const;

        inline Eigen::Vector3f getClearColor() const { return clear_color_; }
        inline Visualizer& setClearColor(const Eigen::Vector3f &color) { clear_color_ = color; return *this; }
        inline Visualizer& setClearColor(float r, float g, float b) { clear_color_ = Eigen::Vector3f(r,g,b); return *this; }

        Visualizer& setProjectionMatrix(int w, int h, pangolin::GLprecision fu, pangolin::GLprecision fv, pangolin::GLprecision u0, pangolin::GLprecision v0, pangolin::GLprecision zNear, pangolin::GLprecision zFar);
        Visualizer& setProjectionMatrix(int w, int h, const Eigen::Matrix3f &intrinsics, pangolin::GLprecision zNear, pangolin::GLprecision zFar);

        Eigen::Matrix4f getCameraPose() const;
        Visualizer& getCameraPose(Eigen::Vector3f &position, Eigen::Vector3f &look_at, Eigen::Vector3f &up_direction) const;
        Visualizer& setCameraPose(const Eigen::Vector3f &position, const Eigen::Vector3f &look_at, const Eigen::Vector3f &up_direction);
        Visualizer& setCameraPose(float pos_x, float pos_y, float pos_z, float look_at_x, float look_at_y, float look_at_z, float up_dir_x, float up_dir_y, float up_dir_z);
        Visualizer& setCameraPose(const Eigen::Matrix4f &pose);

        Visualizer& registerKeyboardCallback(const std::vector<int> &keys, std::function<void(Visualizer&,int,void*)> func, void *cookie);

        pangolin::TypedImage getRenderImage(float scale = 1.0f, bool rgba = false);
        Visualizer& saveRenderAsImage(const std::string &file_name, float scale, float quality, bool rgba = false);

        Visualizer& startVideoRecording(const std::string &uri, size_t fps, bool record_on_render = false, float scale = 1.0f, bool rgba = false);
        Visualizer& recordVideoFrame();
        Visualizer& stopVideoRecording();
        inline bool isRecording() const { return !!video_recorder_; }

        inline pangolin::PangolinGl* getPangolinGLContext() const { return gl_context_; }
        inline pangolin::View* getPangolinDisplay() const { return display_; }

        inline pangolin::OpenGlRenderState* getPangolinRenderState() const { return gl_render_state_.get(); }

    private:
        pangolin::PangolinGl *gl_context_;
        pangolin::View *display_;

        std::shared_ptr<pangolin::OpenGlRenderState> gl_render_state_;
        std::shared_ptr<pangolin::Handler3D> input_handler_;
        pangolin::OpenGlMatrix initial_model_view_;
        std::shared_ptr<pangolin::VideoOutput> video_recorder_;
        size_t video_fps_;
        float video_scale_;
        bool video_rgba_;
        bool video_record_on_render_;
        Eigen::Vector3f clear_color_;
        Eigen::Matrix4f cam_axes_rot_;

        std::map<std::string, std::shared_ptr<Renderable> > renderables_;

        void init_(const std::string &window_name, const std::string &display_name);

        static void point_size_callback_(Visualizer &viz, int key);
        static void reset_view_callback_(Visualizer &viz);
        static void wireframe_toggle_callback_(Visualizer &viz);

        struct {
            inline bool operator() (const std::pair<Renderable*, float> &p1, const std::pair<Renderable*, float> &p2) const {
                bool is_opaque1 = p1.first->renderingProperties.opacity == 1.0f;
                bool is_opaque2 = p2.first->renderingProperties.opacity == 1.0f;
                if (is_opaque1 > is_opaque2) {
                    return true;
                } else if (is_opaque1 < is_opaque2) {
                    return false;
                } else {
                    return p1.second > p2.second;
                }
//                return std::make_pair(p1.first->renderingProperties.opacity == 1.0f, p1.second) > std::make_pair(p2.first->renderingProperties.opacity == 1.0f, p2.second);
            }
        } render_priority_comparator_;
    };
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief FifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-12-10
 */

#ifndef INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_FIFOQUEUE_HPP_

#include "distortos/scheduler/FifoQueueBase.hpp"

namespace distortos
{

/**
 * \brief FifoQueue class is a simple FIFO queue for thread-thread, thread-interrupt or interrupt-interrupt
 * communication. It supports multiple readers and multiple writers. It is implemented as a thin wrapper for
 * scheduler::FifoQueueBase.
 *
 * \param T is the type of data in queue
 */

template<typename T>
class FifoQueue : private scheduler::FifoQueueBase
{
public:

	/// type of uninitialized storage for data
	using Storage = Storage<T>;

	/**
	 * \brief FifoQueue's constructor
	 *
	 * \param [in] storage is an array of Storage elements
	 * \param [in] maxElements is the number of elements in storage array
	 */

	FifoQueue(Storage* const storage, const size_t maxElements) :
			FifoQueueBase{storage, maxElements, TypeTag<T>{}}
	{

	}

	/**
	 * \brief Pops the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::pop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int pop(T& value)
	{
		return FifoQueueBase::pop(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(const T& value)
	{
		return FifoQueueBase::push(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(T&& value)
	{
		return FifoQueueBase::push(std::move(value));
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPop(T& value)
	{
		return FifoQueueBase::tryPop(value);
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPopFor(TickClock::duration, T&)
	 *
	 * \param [in] duration is the duration after which the call will be terminated without popping the element
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWaitFor();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPopFor(const TickClock::duration duration, T& value)
	{
		return FifoQueueBase::tryPopFor(duration, value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(const T& value)
	{
		return FifoQueueBase::tryPush(value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(T&& value)
	{
		return FifoQueueBase::tryPush(std::move(value));
	}
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
<commit_msg>FifoQueue: add FifoQueue::tryPushFor(TickClock::duration, const T&)<commit_after>/**
 * \file
 * \brief FifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2014-12-10
 */

#ifndef INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_FIFOQUEUE_HPP_

#include "distortos/scheduler/FifoQueueBase.hpp"

namespace distortos
{

/**
 * \brief FifoQueue class is a simple FIFO queue for thread-thread, thread-interrupt or interrupt-interrupt
 * communication. It supports multiple readers and multiple writers. It is implemented as a thin wrapper for
 * scheduler::FifoQueueBase.
 *
 * \param T is the type of data in queue
 */

template<typename T>
class FifoQueue : private scheduler::FifoQueueBase
{
public:

	/// type of uninitialized storage for data
	using Storage = Storage<T>;

	/**
	 * \brief FifoQueue's constructor
	 *
	 * \param [in] storage is an array of Storage elements
	 * \param [in] maxElements is the number of elements in storage array
	 */

	FifoQueue(Storage* const storage, const size_t maxElements) :
			FifoQueueBase{storage, maxElements, TypeTag<T>{}}
	{

	}

	/**
	 * \brief Pops the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::pop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int pop(T& value)
	{
		return FifoQueueBase::pop(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(const T& value)
	{
		return FifoQueueBase::push(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(T&& value)
	{
		return FifoQueueBase::push(std::move(value));
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPop(T& value)
	{
		return FifoQueueBase::tryPop(value);
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue for a given duration of time.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPopFor(TickClock::duration, T&)
	 *
	 * \param [in] duration is the duration after which the call will be terminated without popping the element
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWaitFor();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPopFor(const TickClock::duration duration, T& value)
	{
		return FifoQueueBase::tryPopFor(duration, value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(const T& value)
	{
		return FifoQueueBase::tryPush(value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(T&& value)
	{
		return FifoQueueBase::tryPush(std::move(value));
	}

	/**
	 * \brief Tries to push the element to the queue for a given duration of time.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPushFor(TickClock::duration, const T&)
	 *
	 * \param [in] duration is the duration after which the wait will be terminated without pushing the element
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWaitFor();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPushFor(const TickClock::duration duration, const T& value)
	{
		return FifoQueueBase::tryPushFor(duration, value);
	}
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
<|endoftext|>