<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
//------------------------------------------------------------------------------
//
// Run a json script layout file
//
//  - watches an named file and reloads actor tree if the file changes
//    ie run
//       builder-run layout.json
//
//       and edit layout.json in a text editor saving to trigger the reload
//
//------------------------------------------------------------------------------

#include <dali/dali.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/builder/builder.h>
#include <dali-toolkit/devel-api/builder/tree-node.h>
#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <streambuf>

#include "sys/stat.h"
#include <ctime>

#include <dali/integration-api/debug.h>

#define TOKEN_STRING(x) #x

using namespace Dali;
using namespace Dali::Toolkit;

namespace
{

std::string JSON_BROKEN("                                      \
{                                                              \
  'stage':                                                     \
  [                                                            \
    {                                                          \
      'type':'TextActor',                                      \
      'size': [50,50,1],                                       \
      'parentOrigin': 'CENTER',                                \
      'text':'COULD NOT LOAD JSON FILE'                        \
    }                                                          \
  ]                                                            \
}                                                              \
");

std::string ReplaceQuotes(const std::string &single_quoted)
{
  std::string s(single_quoted);

  // wrong as no embedded quote but had regex link problems
  std::replace(s.begin(), s.end(), '\'', '"');

  return s;
}

} // anon namespace

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
class FileWatcher
{
public:
  FileWatcher(void);
  ~FileWatcher(void);
  explicit FileWatcher(const std::string &fn): mLastTime(0) { SetFilename(fn) ; };

  void SetFilename(const std::string &fn);
  std::string GetFilename();

  bool FileHasChanged(void);
  std::string GetFileContents(void) { return GetFileContents(mstringPath) ; };

private:
  // compiler does
  // FileWatcher(const FileWatcher&);
  // FileWatcher &operator=(const FileWatcher &);

  std::time_t mLastTime;
  std::string mstringPath;

  std::string GetFileContents(const std::string &fn)
  {
    std::ifstream t(fn.c_str());
    return std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
  };
};

FileWatcher::FileWatcher(void) : mLastTime(0)
{
}

bool FileWatcher::FileHasChanged(void)
{
  struct stat buf;

  if(0 != stat(mstringPath.c_str(), &buf))
  {
    DALI_LOG_WARNING("File does not exist '%s'\n", mstringPath.c_str());
    return false;
  }
  else
  {
    if(buf.st_mtime > mLastTime)
    {
      mLastTime = buf.st_mtime;
      return true;
    }
    else
    {
      mLastTime = buf.st_mtime;
      return false;
    }
  }

  return false;
}

FileWatcher::~FileWatcher()
{
}

void FileWatcher::SetFilename(const std::string &fn)
{
  mstringPath = fn;
}

std::string FileWatcher::GetFilename(void)
{
  return mstringPath;
}

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
class ExampleApp : public ConnectionTracker
{
public:
  ExampleApp(Application &app) : mApp(app)
  {
    app.InitSignal().Connect(this, &ExampleApp::Create);

  }

  ~ExampleApp() {}

public:
  void SetJSONFilename(std::string const &fn) { fw.SetFilename(fn) ; };

  void Create(Application& app)
  {
    mTimer = Timer::New( 500 ); // ms
    mTimer.TickSignal().Connect( this, &ExampleApp::OnTimer);
    mTimer.Start();

    // Connect to key events in order to exit
    Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleApp::OnKeyEvent);
  }

private:
  Application& mApp;
  Layer mRootLayer;

  FileWatcher fw;
  Timer mTimer;

  void ReloadJsonFile(Builder& builder, Layer& layer)
  {
    Stage stage = Stage::GetCurrent();

    builder = Builder::New();
    builder.QuitSignal().Connect( this, &ExampleApp::OnBuilderQuit );

    Property::Map defaultDirs;
    defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]  = DALI_IMAGE_DIR;
    defaultDirs[ TOKEN_STRING(DALI_MODEL_DIR) ]  = DALI_MODEL_DIR;
    defaultDirs[ TOKEN_STRING(DALI_SCRIPT_DIR) ] = DALI_SCRIPT_DIR;

    builder.AddConstants( defaultDirs );

    if(!layer)
    {
      layer = Layer::New();
      layer.SetParentOrigin(ParentOrigin::CENTER);
      layer.SetAnchorPoint(AnchorPoint::CENTER);
      layer.SetSize( stage.GetRootLayer().GetCurrentSize() );
      stage.GetRootLayer().Add(layer);

      // render tasks may have been setup last load so remove them
      RenderTaskList taskList = stage.GetRenderTaskList();
      if( taskList.GetTaskCount() > 1 )
      {
        typedef std::vector<RenderTask> Collection;
        typedef Collection::iterator ColIter;
        Collection tasks;

        for(unsigned int i = 1; i < taskList.GetTaskCount(); ++i)
        {
          tasks.push_back( taskList.GetTask(i) );
        }

        for(ColIter iter = tasks.begin(); iter != tasks.end(); ++iter)
        {
          taskList.RemoveTask(*iter);
        }

        RenderTask defaultTask = taskList.GetTask(0);
        defaultTask.SetSourceActor( stage.GetRootLayer() );
        defaultTask.SetTargetFrameBuffer( FrameBufferImage() );
      }
    }

    unsigned int numChildren = layer.GetChildCount();

    for(unsigned int i=0; i<numChildren; ++i)
    {
      layer.Remove( layer.GetChildAt(0) );
    }

    std::string data(fw.GetFileContents());

    try
    {
      builder.LoadFromString(data);
    }
    catch(...)
    {
      builder.LoadFromString(ReplaceQuotes(JSON_BROKEN));
    }

    builder.AddActors( layer );

  }

  bool OnTimer(void)
  {
    if(fw.FileHasChanged())
    {
      ReloadJsonFile( mBuilder, mRootLayer );
    }

    return true;
  }

  // Process Key events to Quit on back-key
  void OnKeyEvent( const KeyEvent& event )
  {
    if( event.state == KeyEvent::Down )
    {
      if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
      {
        mApp.Quit();
      }
    }
  }

  void OnBuilderQuit()
  {
    mApp.Quit();
  }

  Builder mBuilder;
};

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
  Application dali_app = Application::New(&argc, &argv);

  ExampleApp app(dali_app);

  if(argc > 1)
  {
    std::cout << "Loading file:" << argc << " " << argv[1] << std::endl;
    app.SetJSONFilename(argv[1]);
  }
  else
  {
    DALI_ASSERT_ALWAYS(!"Specify JSON file on command line\n");
  }

  dali_app.MainLoop();

  return 0;
}
<commit_msg>Always print version with dali-builder<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
//------------------------------------------------------------------------------
//
// Run a json script layout file
//
//  - watches an named file and reloads actor tree if the file changes
//    ie run
//       builder-run layout.json
//
//       and edit layout.json in a text editor saving to trigger the reload
//
//------------------------------------------------------------------------------

#include <dali/dali.h>
#include <dali-toolkit/dali-toolkit.h>
#include <dali-toolkit/devel-api/builder/builder.h>
#include <dali-toolkit/devel-api/builder/tree-node.h>
#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <streambuf>

#include "sys/stat.h"
#include <ctime>

#include <dali/integration-api/debug.h>

#define TOKEN_STRING(x) #x

using namespace Dali;
using namespace Dali::Toolkit;

namespace
{

std::string JSON_BROKEN("                                      \
{                                                              \
  'stage':                                                     \
  [                                                            \
    {                                                          \
      'type':'TextActor',                                      \
      'size': [50,50,1],                                       \
      'parentOrigin': 'CENTER',                                \
      'text':'COULD NOT LOAD JSON FILE'                        \
    }                                                          \
  ]                                                            \
}                                                              \
");

std::string ReplaceQuotes(const std::string &single_quoted)
{
  std::string s(single_quoted);

  // wrong as no embedded quote but had regex link problems
  std::replace(s.begin(), s.end(), '\'', '"');

  return s;
}

} // anon namespace

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
class FileWatcher
{
public:
  FileWatcher(void);
  ~FileWatcher(void);
  explicit FileWatcher(const std::string &fn): mLastTime(0) { SetFilename(fn) ; };

  void SetFilename(const std::string &fn);
  std::string GetFilename();

  bool FileHasChanged(void);
  std::string GetFileContents(void) { return GetFileContents(mstringPath) ; };

private:
  // compiler does
  // FileWatcher(const FileWatcher&);
  // FileWatcher &operator=(const FileWatcher &);

  std::time_t mLastTime;
  std::string mstringPath;

  std::string GetFileContents(const std::string &fn)
  {
    std::ifstream t(fn.c_str());
    return std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
  };
};

FileWatcher::FileWatcher(void) : mLastTime(0)
{
}

bool FileWatcher::FileHasChanged(void)
{
  struct stat buf;

  if(0 != stat(mstringPath.c_str(), &buf))
  {
    DALI_LOG_WARNING("File does not exist '%s'\n", mstringPath.c_str());
    return false;
  }
  else
  {
    if(buf.st_mtime > mLastTime)
    {
      mLastTime = buf.st_mtime;
      return true;
    }
    else
    {
      mLastTime = buf.st_mtime;
      return false;
    }
  }

  return false;
}

FileWatcher::~FileWatcher()
{
}

void FileWatcher::SetFilename(const std::string &fn)
{
  mstringPath = fn;
}

std::string FileWatcher::GetFilename(void)
{
  return mstringPath;
}

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
class ExampleApp : public ConnectionTracker
{
public:
  ExampleApp(Application &app) : mApp(app)
  {
    app.InitSignal().Connect(this, &ExampleApp::Create);

  }

  ~ExampleApp() {}

public:
  void SetJSONFilename(std::string const &fn) { fw.SetFilename(fn) ; };

  void Create(Application& app)
  {
    mTimer = Timer::New( 500 ); // ms
    mTimer.TickSignal().Connect( this, &ExampleApp::OnTimer);
    mTimer.Start();

    // Connect to key events in order to exit
    Stage::GetCurrent().KeyEventSignal().Connect(this, &ExampleApp::OnKeyEvent);
  }

private:
  Application& mApp;
  Layer mRootLayer;

  FileWatcher fw;
  Timer mTimer;

  void ReloadJsonFile(Builder& builder, Layer& layer)
  {
    Stage stage = Stage::GetCurrent();

    builder = Builder::New();
    builder.QuitSignal().Connect( this, &ExampleApp::OnBuilderQuit );

    Property::Map defaultDirs;
    defaultDirs[ TOKEN_STRING(DALI_IMAGE_DIR) ]  = DALI_IMAGE_DIR;
    defaultDirs[ TOKEN_STRING(DALI_MODEL_DIR) ]  = DALI_MODEL_DIR;
    defaultDirs[ TOKEN_STRING(DALI_SCRIPT_DIR) ] = DALI_SCRIPT_DIR;

    builder.AddConstants( defaultDirs );

    if(!layer)
    {
      layer = Layer::New();
      layer.SetParentOrigin(ParentOrigin::CENTER);
      layer.SetAnchorPoint(AnchorPoint::CENTER);
      layer.SetSize( stage.GetRootLayer().GetCurrentSize() );
      stage.GetRootLayer().Add(layer);

      // render tasks may have been setup last load so remove them
      RenderTaskList taskList = stage.GetRenderTaskList();
      if( taskList.GetTaskCount() > 1 )
      {
        typedef std::vector<RenderTask> Collection;
        typedef Collection::iterator ColIter;
        Collection tasks;

        for(unsigned int i = 1; i < taskList.GetTaskCount(); ++i)
        {
          tasks.push_back( taskList.GetTask(i) );
        }

        for(ColIter iter = tasks.begin(); iter != tasks.end(); ++iter)
        {
          taskList.RemoveTask(*iter);
        }

        RenderTask defaultTask = taskList.GetTask(0);
        defaultTask.SetSourceActor( stage.GetRootLayer() );
        defaultTask.SetTargetFrameBuffer( FrameBufferImage() );
      }
    }

    unsigned int numChildren = layer.GetChildCount();

    for(unsigned int i=0; i<numChildren; ++i)
    {
      layer.Remove( layer.GetChildAt(0) );
    }

    std::string data(fw.GetFileContents());

    try
    {
      builder.LoadFromString(data);
    }
    catch(...)
    {
      builder.LoadFromString(ReplaceQuotes(JSON_BROKEN));
    }

    builder.AddActors( layer );

  }

  bool OnTimer(void)
  {
    if(fw.FileHasChanged())
    {
      ReloadJsonFile( mBuilder, mRootLayer );
    }

    return true;
  }

  // Process Key events to Quit on back-key
  void OnKeyEvent( const KeyEvent& event )
  {
    if( event.state == KeyEvent::Down )
    {
      if( IsKey( event, Dali::DALI_KEY_ESCAPE ) || IsKey( event, Dali::DALI_KEY_BACK ) )
      {
        mApp.Quit();
      }
    }
  }

  void OnBuilderQuit()
  {
    mApp.Quit();
  }

  Builder mBuilder;
};

//------------------------------------------------------------------------------
//
//
//
//------------------------------------------------------------------------------
int main(int argc, char **argv)
{
  Application dali_app = Application::New(&argc, &argv);

  ExampleApp app(dali_app);

  std::cout << "DALi Core: \t" << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << " (" << CORE_BUILD_DATE << ")" << std::endl;
  std::cout << "DALi Adaptor: \t" << ADAPTOR_MAJOR_VERSION << "." << ADAPTOR_MINOR_VERSION << "." << ADAPTOR_MICRO_VERSION << " (" << ADAPTOR_BUILD_DATE << ")\n";
  std::cout << "DALi Toolkit: \t" << Toolkit::TOOLKIT_MAJOR_VERSION << "." << Toolkit::TOOLKIT_MINOR_VERSION << "." << Toolkit::TOOLKIT_MICRO_VERSION << " (" << Toolkit::TOOLKIT_BUILD_DATE << ")\n";

  if(argc > 1)
  {
    std::cout << "Loading file:" << argc << " " << argv[1] << std::endl;
    app.SetJSONFilename(argv[1]);
  }
  else
  {
    DALI_ASSERT_ALWAYS(!"Specify JSON file on command line\n");
  }

  dali_app.MainLoop();

  return 0;
}
<|endoftext|>


<commit_before>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/RhoPort.h"
#include "ext/rho/rhoruby.h"

extern "C" {

void mapview_create(rho_param *p)
{
    //TODO: mapview_create
}

void mapview_close()
{
    //TODO: mapview_close
}

VALUE mapview_state_started()
{
    //TODO: mapview_state_started
    return rho_ruby_create_boolean(0);
}

double mapview_state_center_lat()
{
    //TODO: mapview_state_center_lat
    return 0.;
}

double mapview_state_center_lon()
{
    //TODO: mapview_state_center_lon
    return 0.;
}

} //extern "C"
<commit_msg>fixed linkage bug<commit_after>/*------------------------------------------------------------------------
* (The MIT License)
*
* Copyright (c) 2008-2011 Rhomobile, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* http://rhomobile.com
*------------------------------------------------------------------------*/

#include "common/RhoPort.h"
#include "ext/rho/rhoruby.h"

extern "C" {

void mapview_create(rho_param *p)
{
    //TODO: mapview_create
}

void mapview_close()
{
    //TODO: mapview_close
}

VALUE mapview_state_started()
{
    //TODO: mapview_state_started
    return rho_ruby_create_boolean(0);
}

double mapview_state_center_lat()
{
    //TODO: mapview_state_center_lat
    return 0.;
}

double mapview_state_center_lon()
{
    //TODO: mapview_state_center_lon
    return 0.;
}

void mapview_set_file_caching_enable(int enable)
{
}

} //extern "C"
<|endoftext|>


<commit_before> /*************************************************************************
 *
 *  $RCSfile: tolayoutanchoredobjectposition.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-03-08 13:59:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _TOLAYOUTANCHOREDOBJECTPOSITION_HXX
#define _TOLAYOUTANCHOREDOBJECTPOSITION_HXX

#ifndef _ANCHOREDOBJECTPOSITION_HXX
#include <anchoredobjectposition.hxx>
#endif
#ifndef _SWTYPES_HXX
#include <swtypes.hxx>
#endif
#ifndef _SWRECT_HXX
#include <swrect.hxx>
#endif
#ifndef _ORNTENUM_HXX
#include <orntenum.hxx>
#endif

class SwFlyLayFrm;
class SvxLRSpaceItem;
class SvxULSpaceItem;

namespace objectpositioning
{
    class SwToLayoutAnchoredObjectPosition : public SwAnchoredObjectPosition
    {
        private:
            // calculated data for object position type TO_LAYOUT
            Point       maRelPos;

            // method to cast <SwAnchoredObjectPosition::GetFrmOfObj()> to
            // the needed type
            SwFlyLayFrm* GetFlyLayFrmOfObj() const;

        public:
            SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj );
            ~SwToLayoutAnchoredObjectPosition();

            /** calculate position for object

                OD 30.07.2003 #110978#

                @author OD
            */
            virtual void CalcPosition();

            /** calculated relative position for object

                @author OD
            */
            Point GetRelPos() const;
    };
};

#endif
<commit_msg>INTEGRATION: CWS swdrawpositioning (1.2.6); FILE MERGED 2004/06/17 10:21:32 od 1.2.6.2: #i26791# - further adjustments for the unification of the positioning 	   of Writer fly frames and drawing objects. 2004/04/07 11:59:19 od 1.2.6.1: #i26791# - adjustments for the unification of the positioning of 	   Writer fly frames and drawing objects<commit_after> /*************************************************************************
 *
 *  $RCSfile: tolayoutanchoredobjectposition.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hjs $ $Date: 2004-06-28 13:37:15 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _TOLAYOUTANCHOREDOBJECTPOSITION_HXX
#define _TOLAYOUTANCHOREDOBJECTPOSITION_HXX

#ifndef _ANCHOREDOBJECTPOSITION_HXX
#include <anchoredobjectposition.hxx>
#endif
#ifndef _SWTYPES_HXX
#include <swtypes.hxx>
#endif
#ifndef _SWRECT_HXX
#include <swrect.hxx>
#endif
#ifndef _ORNTENUM_HXX
#include <orntenum.hxx>
#endif

class SwFlyLayFrm;
class SvxLRSpaceItem;
class SvxULSpaceItem;

namespace objectpositioning
{
    class SwToLayoutAnchoredObjectPosition : public SwAnchoredObjectPosition
    {
        private:
            // calculated data for object position type TO_LAYOUT
            Point maRelPos;
            // --> OD 2004-06-17 #i26791#
            // determine offset to frame anchor position according to the
            // positioning alignments
            Point maOffsetToFrmAnchorPos;

        public:
            SwToLayoutAnchoredObjectPosition( SdrObject& _rDrawObj );
            ~SwToLayoutAnchoredObjectPosition();

            /** calculate position for object

                OD 30.07.2003 #110978#

                @author OD
            */
            virtual void CalcPosition();

            /** calculated relative position for object

                @author OD
            */
            Point GetRelPos() const;

            /** determined offset to frame anchor position

                --> OD 2004-06-17 #i26791#

                @author OD
            */
            Point GetOffsetToFrmAnchorPos() const;
    };
};

#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/ocmb/odyssey/procedures/hwp/memory/lib/mcbist/ody_memdiags.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2019,2022                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// EKB-Mirror-To: hostboot

///
/// @file ody_memdiags.C
/// @brief Run and manage the MEMDIAGS engine
///
// *HWP HWP Owner: Sneha Kadam <sneha.kadam1@ibm.com>
// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <lib/dimm/ody_rank.H>
#include <lib/mcbist/ody_memdiags.H>
#include <lib/mcbist/ody_mcbist.H>
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/poll.H>

namespace mss
{

namespace memdiags
{

///
/// @brief Mask MCBISTFIRQ[MCBIST_PROGRAM_COMPLETE] and return the original mask value - specialization for Odyssey
/// @param[in] i_target the target
/// @param[out] o_fir_mask_save the original mask value to be restored later
/// @return FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode mask_program_complete<mss::mc_type::ODYSSEY>(
    const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
    fapi2::buffer<uint64_t>& o_fir_mask_save )
{
    using TT = mss::mcbistTraits<mss::mc_type::ODYSSEY, fapi2::TARGET_TYPE_OCMB_CHIP>;

    fapi2::buffer<uint64_t> l_fir_mask;

    // Mask the FIR
    // Todo: ZEN:MST-1660 Implement FIR_MASK_REG
    //FAPI_TRY( mss::getScom(i_target, TT::FIRQ_MASK_REG, o_fir_mask_save) );
    l_fir_mask = o_fir_mask_save;
    l_fir_mask.setBit<TT::MCB_PROGRAM_COMPLETE>();
    // Todo: ZEN:MST-1660 Implement FIR_MASK_REG
    //FAPI_TRY( mss::putScom(i_target, TT::FIRQ_MASK_REG, l_fir_mask) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Restore MCBISTFIRQ[MCBIST_PROGRAM_COMPLETE] mask value and clear the FIR - specialization for Odyssey
/// @param[in] i_target the target
/// @param[in] i_fir_mask_save the original mask value to be restored
/// @return FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode clear_and_restore_program_complete<mss::mc_type::ODYSSEY>(
    const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
    const fapi2::buffer<uint64_t>& i_fir_mask_save )
{
    using TT = mss::mcbistTraits<mss::mc_type::ODYSSEY, fapi2::TARGET_TYPE_OCMB_CHIP>;

    fapi2::buffer<uint64_t> l_fir;

    // Clear the FIR
    FAPI_TRY( mss::getScom(i_target, TT::FIRQ_REG, l_fir) );
    l_fir.clearBit<TT::MCB_PROGRAM_COMPLETE>();
    FAPI_TRY( mss::putScom(i_target, TT::FIRQ_REG, l_fir) );

    // Then restore the mask value
    // Todo: ZEN:MST-1660 Implement FIR_MASK_REG
    //FAPI_TRY( mss::putScom(i_target, TT::FIRQ_MASK_REG, i_fir_mask_save) );

fapi_try_exit:
    return fapi2::current_err;
}

} // memdiags
} // namespace mss
<commit_msg>Fixes Odyssey memdiags FIR masking functionality<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/ocmb/odyssey/procedures/hwp/memory/lib/mcbist/ody_memdiags.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2019,2022                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// EKB-Mirror-To: hostboot

///
/// @file ody_memdiags.C
/// @brief Run and manage the MEMDIAGS engine
///
// *HWP HWP Owner: Sneha Kadam <sneha.kadam1@ibm.com>
// *HWP HWP Backup: Marc Gollub <gollub@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <lib/dimm/ody_rank.H>
#include <lib/mcbist/ody_memdiags.H>
#include <lib/mcbist/ody_mcbist.H>
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/poll.H>

namespace mss
{

namespace memdiags
{

///
/// @brief Mask MCBISTFIRQ[MCBIST_PROGRAM_COMPLETE] and return the original mask value - specialization for Odyssey
/// @param[in] i_target the target
/// @param[out] o_fir_mask_save the original mask value to be restored later
/// @return FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode mask_program_complete<mss::mc_type::ODYSSEY>(
    const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
    fapi2::buffer<uint64_t>& o_fir_mask_save )
{
    using TT = mss::mcbistTraits<mss::mc_type::ODYSSEY, fapi2::TARGET_TYPE_OCMB_CHIP>;

    fapi2::buffer<uint64_t> l_fir_mask;

    // Mask the FIR
    l_fir_mask.setBit<TT::MCB_PROGRAM_COMPLETE>();
    o_fir_mask_save = l_fir_mask;
    FAPI_TRY( mss::putScom(i_target, scomt::ody::ODC_MCBIST_SCOM_MCBISTFIRMASK_WO_OR, l_fir_mask) );

fapi_try_exit:
    return fapi2::current_err;
}

///
/// @brief Restore MCBISTFIRQ[MCBIST_PROGRAM_COMPLETE] mask value and clear the FIR - specialization for Odyssey
/// @param[in] i_target the target
/// @param[in] i_fir_mask_save the original mask value to be restored
/// @return FAPI2_RC_SUCCESS iff ok
///
template<>
fapi2::ReturnCode clear_and_restore_program_complete<mss::mc_type::ODYSSEY>(
    const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
    const fapi2::buffer<uint64_t>& i_fir_mask_save )
{
    using TT = mss::mcbistTraits<mss::mc_type::ODYSSEY, fapi2::TARGET_TYPE_OCMB_CHIP>;

    fapi2::buffer<uint64_t> l_fir;

    // Clear the FIR
    // The FIRQ register for Odyssey has a write clear functionality
    // Any bit set to a 1 will clear out the FIR in this register
    l_fir.setBit<TT::MCB_PROGRAM_COMPLETE>();
    FAPI_TRY( mss::putScom(i_target, TT::FIRQ_REG, l_fir) );

    // Then restore the mask value
    FAPI_TRY( mss::putScom(i_target, scomt::ody::ODC_MCBIST_SCOM_MCBISTFIRMASK_RW_WCLEAR, i_fir_mask_save) );

fapi_try_exit:
    return fapi2::current_err;
}

} // memdiags
} // namespace mss
<|endoftext|>


<commit_before>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "progress-bar.hh"

using namespace nix;

struct CmdLog : InstallableCommand
{
    CmdLog()
    {
    }

    std::string name() override
    {
        return "log";
    }

    std::string description() override
    {
        return "show the build log of the specified packages or paths, if available";
    }

    Examples examples() override
    {
        return {
            Example{
                "To get the build log of GNU Hello:",
                "nix log nixpkgs.hello"
            },
            Example{
                "To get the build log of a specific path:",
                "nix log /nix/store/lmngj4wcm9rkv3w4dfhzhcyij3195hiq-thunderbird-52.2.1"
            },
            Example{
                "To get a build log from a specific binary cache:",
                "nix log --store https://cache.nixos.org nixpkgs.hello"
            },
        };
    }

    void run(ref<Store> store) override
    {
        settings.readOnlyMode = true;

        auto subs = getDefaultSubstituters();

        subs.push_front(store);

        auto b = installable->toBuildable();

        RunPager pager;
        for (auto & sub : subs) {
            auto log = b.drvPath != "" ? sub->getBuildLog(b.drvPath) : nullptr;
            for (auto & output : b.outputs) {
                if (log) break;
                log = sub->getBuildLog(output.second);
            }
            if (!log) continue;
            stopProgressBar();
            printInfo("got build log for '%s' from '%s'", installable->what(), sub->getUri());
            std::cout << *log;
            return;
        }

        throw Error("build log of '%s' is not available", installable->what());
    }
};

static RegisterCommand r1(make_ref<CmdLog>());
<commit_msg>nix log: only run pager if log found, not on error<commit_after>#include "command.hh"
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
#include "progress-bar.hh"

using namespace nix;

struct CmdLog : InstallableCommand
{
    CmdLog()
    {
    }

    std::string name() override
    {
        return "log";
    }

    std::string description() override
    {
        return "show the build log of the specified packages or paths, if available";
    }

    Examples examples() override
    {
        return {
            Example{
                "To get the build log of GNU Hello:",
                "nix log nixpkgs.hello"
            },
            Example{
                "To get the build log of a specific path:",
                "nix log /nix/store/lmngj4wcm9rkv3w4dfhzhcyij3195hiq-thunderbird-52.2.1"
            },
            Example{
                "To get a build log from a specific binary cache:",
                "nix log --store https://cache.nixos.org nixpkgs.hello"
            },
        };
    }

    void run(ref<Store> store) override
    {
        settings.readOnlyMode = true;

        auto subs = getDefaultSubstituters();

        subs.push_front(store);

        auto b = installable->toBuildable();
        std::string what = installable->what();
        auto showLog = [what](auto log, auto & sub) {
          RunPager pager;
          stopProgressBar();
          printInfo("got build log for '%s' from '%s'", what, sub->getUri());
          std::cout << *log;
        };
        for (auto & sub : subs) {
            if (b.drvPath != "") {
                if (auto log = sub->getBuildLog(b.drvPath))
                    return showLog(log, sub);
            }
            for (auto &output : b.outputs)
                if (auto log = sub->getBuildLog(output.second))
                    return showLog(log, sub);
        }
        throw Error("build log of '%s' is not available", what);
    }
};

static RegisterCommand r1(make_ref<CmdLog>());
<|endoftext|>


<commit_before>/*
 *
 *  D-Bus++ - C++ bindings for D-Bus
 *
 *  Copyright (C) 2005-2007  Paolo Durante <shackan@gmail.com>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <dbus-c++/debug.h>
#include <dbus-c++/object.h>
#include "internalerror.h"

#include <cstring>
#include <map>
#include <dbus/dbus.h>

#include "message_p.h"
#include "server_p.h"
#include "connection_p.h"

using namespace DBus;

Object::Object(Connection &conn, const Path &path, const char *service)
: _conn(conn), _path(path), _service(service ? service : "")
{
}

Object::~Object()
{
}

struct ObjectAdaptor::Private
{
	static void unregister_function_stub(DBusConnection *, void *);
	static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *);
};

static DBusObjectPathVTable _vtable =
{
	ObjectAdaptor::Private::unregister_function_stub,
	ObjectAdaptor::Private::message_function_stub,
	NULL, NULL, NULL, NULL
};

void ObjectAdaptor::Private::unregister_function_stub(DBusConnection *conn, void *data)
{
 	//TODO: what do we have to do here ?
}

DBusHandlerResult ObjectAdaptor::Private::message_function_stub(DBusConnection *, DBusMessage *dmsg, void *data)
{
	ObjectAdaptor *o = static_cast<ObjectAdaptor *>(data);

	if (o)
	{
		Message msg(new Message::Private(dmsg));

		debug_log("in object %s", o->path().c_str());
		debug_log(" got message #%d from %s to %s",
			msg.serial(),
			msg.sender(),
			msg.destination()
		);

		return o->handle_message(msg)
			? DBUS_HANDLER_RESULT_HANDLED
			: DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}
	else
	{
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}
}

typedef std::map<Path, ObjectAdaptor *> ObjectAdaptorTable;
static ObjectAdaptorTable _adaptor_table;

ObjectAdaptor *ObjectAdaptor::from_path(const Path &path)
{
	ObjectAdaptorTable::iterator ati = _adaptor_table.find(path);

	if (ati != _adaptor_table.end())
		return ati->second;

	return NULL;
}

ObjectAdaptorPList ObjectAdaptor::from_path_prefix(const std::string &prefix)
{
	ObjectAdaptorPList ali;

	ObjectAdaptorTable::iterator ati = _adaptor_table.begin();

	size_t plen = prefix.length();

	while (ati != _adaptor_table.end())
	{
		if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
			ali.push_back(ati->second);

		++ati;
	}

	return ali;
}

ObjectPathList ObjectAdaptor::child_nodes_from_prefix(const std::string &prefix)
{
	ObjectPathList ali;

	ObjectAdaptorTable::iterator ati = _adaptor_table.begin();

	size_t plen = prefix.length();

	while (ati != _adaptor_table.end())
	{
	  if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
		{
				std::string p = ati->second->path().substr(plen);
				p = p.substr(0,p.find('/'));
				ali.push_back(p);
		}
		++ati;
	}

	ali.sort();
	ali.unique();

	return ali;
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path)
: Object(conn, path, conn.unique_name()), _eflag(USE_EXCEPTIONS)
{
	register_obj();
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path, registration_time rtime)
: Object(conn, path, conn.unique_name()), _eflag(USE_EXCEPTIONS)
{
	if (rtime == REGISTER_NOW)
		register_obj();
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path, registration_time rtime,
				exceptions_flag eflag)
: Object(conn, path, conn.unique_name()), _eflag(eflag)
{
	if (rtime == REGISTER_NOW)
		register_obj();
}

ObjectAdaptor::~ObjectAdaptor()
{
	unregister_obj();
}

void ObjectAdaptor::register_obj()
{
	debug_log("registering local object %s", path().c_str());

	if (!dbus_connection_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this))
	{
 		throw ErrorNoMemory("unable to register object path");
	}

	_adaptor_table[path()] = this;
}

void ObjectAdaptor::unregister_obj()
{
	if (!is_registered())
		return;

	_adaptor_table.erase(path());

	debug_log("unregistering local object %s", path().c_str());

	dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str());
}

bool ObjectAdaptor::is_registered()
{
	return _adaptor_table.find(path()) != _adaptor_table.end();
}

void ObjectAdaptor::_emit_signal(SignalMessage &sig)
{
	sig.path(path().c_str());

	conn().send(sig);
}

struct ReturnLaterError
{
	const Tag *tag;
};

bool ObjectAdaptor::handle_message(const Message &msg)
{
	switch (msg.type())
	{
		case DBUS_MESSAGE_TYPE_METHOD_CALL:
		{
			const CallMessage &cmsg = reinterpret_cast<const CallMessage &>(msg);
			const char *member      = cmsg.member();
			const char *interface   = cmsg.interface();

			debug_log(" invoking method %s.%s", interface, member);

			InterfaceAdaptor *ii = find_interface(interface);
			if (ii)
			{
				if (_eflag == AVOID_EXCEPTIONS) {
					Message ret = ii->dispatch_method(cmsg);
					Tag *tag = ret.tag();
					if (tag) {
						_continuations[tag] =
						    new Continuation(conn(), cmsg, tag);
					} else {
						conn().send(ret);
					}
					return true;
				}
				// TODO(jglasgow@google.com): make this code
				// conditional based on compile time option to
				// support exceptions.
				try
				{
					Message ret = ii->dispatch_method(cmsg);
					conn().send(ret);
				}
				catch(Error &e)
				{
					ErrorMessage em(cmsg, e.name(), e.message());
					conn().send(em);
				}
				catch(ReturnLaterError &rle)
				{
					_continuations[rle.tag] = new Continuation(conn(), cmsg, rle.tag);
				}
				return true;
			}
			else
			{
				return false;
			}
		}
		default:
		{
			return false;
		}
	}
}

void ObjectAdaptor::return_later(const Tag *tag)
{
	ReturnLaterError rle = { tag };
	throw rle;
}

void ObjectAdaptor::return_now(Continuation *ret)
{
	ret->_conn.send(ret->_return);

	ContinuationMap::iterator di = _continuations.find(ret->_tag);

	delete di->second;

	_continuations.erase(di);
}

void ObjectAdaptor::return_error(Continuation *ret, const Error error)
{
	ret->_conn.send(ErrorMessage(ret->_call, error.name(), error.message()));

	ContinuationMap::iterator di = _continuations.find(ret->_tag);

	delete di->second;

	_continuations.erase(di);
}

ObjectAdaptor::Continuation *ObjectAdaptor::find_continuation(const Tag *tag)
{
	ContinuationMap::iterator di = _continuations.find(tag);

	return di != _continuations.end() ? di->second : NULL;
}

ObjectAdaptor::Continuation::Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
: _conn(conn), _call(call), _return(_call), _tag(tag)
{
	_writer = _return.writer(); //todo: verify
}

/*
*/

ObjectProxy::ObjectProxy(Connection &conn, const Path &path, const char *service)
: Object(conn, path, service)
{
	register_obj();
}

// TODO(ers@google.com): unregister_obj() makes a synchronous
// dbus method call, which can result in a deadlock if the
// ObjectProxy is deleted while in a callback from a signal
// or a pending call reply.
ObjectProxy::~ObjectProxy()
{
	cancel_pending_calls();
	unregister_obj();
}

void ObjectProxy::cancel_pending_calls()
{
	PendingCallList::const_iterator pi = _pending_calls.begin();
	while (pi != _pending_calls.end())
	{
		(*pi)->cancel();
		delete *pi;
		++pi;
	}
	_pending_calls.clear();
}

void ObjectProxy::_remove_pending_call(PendingCall *pending)
{
	PendingCallList::iterator pi = _pending_calls.begin();
	while (pi != _pending_calls.end())
	{
		if (*pi == pending)
		{
			_pending_calls.erase(pi);
			break;
		}
		++pi;
	}
	delete pending;
}

void ObjectProxy::register_obj()
{
	debug_log("registering remote object %s", path().c_str());

	_filtered = new Callback<ObjectProxy, bool, const Message &>(this, &ObjectProxy::handle_message);

	conn().add_filter(_filtered);

	InterfaceProxyTable::const_iterator ii = _interfaces.begin();
	while (ii != _interfaces.end())
	{
		std::string im = "type='signal',interface='"+ii->first+"',path='"+path()+"'";
		conn().add_match(im.c_str());
		++ii;
	}
}

void ObjectProxy::unregister_obj()
{
	debug_log("unregistering remote object %s", path().c_str());

	InterfaceProxyTable::const_iterator ii = _interfaces.begin();
	while (ii != _interfaces.end())
	{
		std::string im = "type='signal',interface='"+ii->first+"',path='"+path()+"'";
		conn().remove_match(im.c_str());
		++ii;
	}
	conn().remove_filter(_filtered);
}

bool ObjectProxy::is_registered()
{
	return true;
}

Message ObjectProxy::_invoke_method(CallMessage &call)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	return conn().send_blocking(call);
}

bool ObjectProxy::_invoke_method_noreply(CallMessage &call)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	return conn().send(call);
}

PendingCall *ObjectProxy::_invoke_method_async(CallMessage &call, int timeout)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	PendingCall *pending = conn().send_async(call, timeout);
	_pending_calls.push_back(pending);
	return pending;
}

bool ObjectProxy::handle_message(const Message &msg)
{
	switch (msg.type())
	{
		case DBUS_MESSAGE_TYPE_SIGNAL:
		{
			const SignalMessage &smsg = reinterpret_cast<const SignalMessage &>(msg);
			const char *interface	= smsg.interface();
			const char *member	= smsg.member();
			const char *objpath	= smsg.path();

			if (objpath != path()) return false;

			debug_log("filtered signal %s(in %s) from %s to object %s",
				member, interface, msg.sender(), objpath);

			InterfaceProxy *ii = find_interface(interface);
			if (ii)
			{
				return ii->dispatch_signal(smsg);
			}
			else
			{
				return false;
			}
		}
		default:
		{
			return false;
		}
	}
}
<commit_msg>DBus-C++: Improving crash analysis with finer-grained exceptions.<commit_after>/*
 *
 *  D-Bus++ - C++ bindings for D-Bus
 *
 *  Copyright (C) 2005-2007  Paolo Durante <shackan@gmail.com>
 *
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <dbus-c++/debug.h>
#include <dbus-c++/object.h>
#include "internalerror.h"

#include <cstring>
#include <map>
#include <dbus/dbus.h>

#include "message_p.h"
#include "server_p.h"
#include "connection_p.h"

using namespace DBus;

Object::Object(Connection &conn, const Path &path, const char *service)
: _conn(conn), _path(path), _service(service ? service : "")
{
}

Object::~Object()
{
}

struct ObjectAdaptor::Private
{
	static void unregister_function_stub(DBusConnection *, void *);
	static DBusHandlerResult message_function_stub(DBusConnection *, DBusMessage *, void *);
};

static DBusObjectPathVTable _vtable =
{
	ObjectAdaptor::Private::unregister_function_stub,
	ObjectAdaptor::Private::message_function_stub,
	NULL, NULL, NULL, NULL
};

void ObjectAdaptor::Private::unregister_function_stub(DBusConnection *conn, void *data)
{
 	//TODO: what do we have to do here ?
}

DBusHandlerResult ObjectAdaptor::Private::message_function_stub(DBusConnection *, DBusMessage *dmsg, void *data)
{
	ObjectAdaptor *o = static_cast<ObjectAdaptor *>(data);

	if (o)
	{
		Message msg(new Message::Private(dmsg));

		debug_log("in object %s", o->path().c_str());
		debug_log(" got message #%d from %s to %s",
			msg.serial(),
			msg.sender(),
			msg.destination()
		);

		return o->handle_message(msg)
			? DBUS_HANDLER_RESULT_HANDLED
			: DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}
	else
	{
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
	}
}

typedef std::map<Path, ObjectAdaptor *> ObjectAdaptorTable;
static ObjectAdaptorTable _adaptor_table;

ObjectAdaptor *ObjectAdaptor::from_path(const Path &path)
{
	ObjectAdaptorTable::iterator ati = _adaptor_table.find(path);

	if (ati != _adaptor_table.end())
		return ati->second;

	return NULL;
}

ObjectAdaptorPList ObjectAdaptor::from_path_prefix(const std::string &prefix)
{
	ObjectAdaptorPList ali;

	ObjectAdaptorTable::iterator ati = _adaptor_table.begin();

	size_t plen = prefix.length();

	while (ati != _adaptor_table.end())
	{
		if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
			ali.push_back(ati->second);

		++ati;
	}

	return ali;
}

ObjectPathList ObjectAdaptor::child_nodes_from_prefix(const std::string &prefix)
{
	ObjectPathList ali;

	ObjectAdaptorTable::iterator ati = _adaptor_table.begin();

	size_t plen = prefix.length();

	while (ati != _adaptor_table.end())
	{
	  if (!strncmp(ati->second->path().c_str(), prefix.c_str(), plen))
		{
				std::string p = ati->second->path().substr(plen);
				p = p.substr(0,p.find('/'));
				ali.push_back(p);
		}
		++ati;
	}

	ali.sort();
	ali.unique();

	return ali;
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path)
: Object(conn, path, conn.unique_name()), _eflag(USE_EXCEPTIONS)
{
	register_obj();
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path, registration_time rtime)
: Object(conn, path, conn.unique_name()), _eflag(USE_EXCEPTIONS)
{
	if (rtime == REGISTER_NOW)
		register_obj();
}

ObjectAdaptor::ObjectAdaptor(Connection &conn, const Path &path, registration_time rtime,
				exceptions_flag eflag)
: Object(conn, path, conn.unique_name()), _eflag(eflag)
{
	if (rtime == REGISTER_NOW)
		register_obj();
}

ObjectAdaptor::~ObjectAdaptor()
{
	unregister_obj();
}

void ObjectAdaptor::register_obj()
{
	debug_log("registering local object %s", path().c_str());

        if (conn()._pvt->conn == NULL)
        {
                throw ErrorInvalidArgs("NULL connection");
        }
        else if (path().c_str() == NULL)
        {
                throw ErrorInvalidArgs("NULL path");
        }
        else if (path().c_str()[0] != '/')
        {
                std::string message = "Path must start with '/': " + path();
                throw ErrorInvalidArgs(message.c_str());
        }

	if (!dbus_connection_register_object_path(conn()._pvt->conn, path().c_str(), &_vtable, this))
	{
 		throw ErrorNoMemory("unable to register object path");
	}

	_adaptor_table[path()] = this;
}

void ObjectAdaptor::unregister_obj()
{
	if (!is_registered())
		return;

	_adaptor_table.erase(path());

	debug_log("unregistering local object %s", path().c_str());

        if (conn()._pvt->conn == NULL)
        {
                throw ErrorInvalidArgs("NULL connection");
        }
        else if (path().c_str() == NULL)
        {
                throw ErrorInvalidArgs("NULL path");
        }
        else if (path().c_str()[0] != '/')
        {
                std::string message = "Path must start with '/': " + path();
                throw ErrorInvalidArgs(message.c_str());
        }

	dbus_connection_unregister_object_path(conn()._pvt->conn, path().c_str());
}

bool ObjectAdaptor::is_registered()
{
	return _adaptor_table.find(path()) != _adaptor_table.end();
}

void ObjectAdaptor::_emit_signal(SignalMessage &sig)
{
	sig.path(path().c_str());

	conn().send(sig);
}

struct ReturnLaterError
{
	const Tag *tag;
};

bool ObjectAdaptor::handle_message(const Message &msg)
{
	switch (msg.type())
	{
		case DBUS_MESSAGE_TYPE_METHOD_CALL:
		{
			const CallMessage &cmsg = reinterpret_cast<const CallMessage &>(msg);
			const char *member      = cmsg.member();
			const char *interface   = cmsg.interface();

			debug_log(" invoking method %s.%s", interface, member);

			InterfaceAdaptor *ii = find_interface(interface);
			if (ii)
			{
				if (_eflag == AVOID_EXCEPTIONS) {
					Message ret = ii->dispatch_method(cmsg);
					Tag *tag = ret.tag();
					if (tag) {
						_continuations[tag] =
						    new Continuation(conn(), cmsg, tag);
					} else {
						conn().send(ret);
					}
					return true;
				}
				// TODO(jglasgow@google.com): make this code
				// conditional based on compile time option to
				// support exceptions.
				try
				{
					Message ret = ii->dispatch_method(cmsg);
					conn().send(ret);
				}
				catch(Error &e)
				{
					ErrorMessage em(cmsg, e.name(), e.message());
					conn().send(em);
				}
				catch(ReturnLaterError &rle)
				{
					_continuations[rle.tag] = new Continuation(conn(), cmsg, rle.tag);
				}
				return true;
			}
			else
			{
				return false;
			}
		}
		default:
		{
			return false;
		}
	}
}

void ObjectAdaptor::return_later(const Tag *tag)
{
	ReturnLaterError rle = { tag };
	throw rle;
}

void ObjectAdaptor::return_now(Continuation *ret)
{
	ret->_conn.send(ret->_return);

	ContinuationMap::iterator di = _continuations.find(ret->_tag);

	delete di->second;

	_continuations.erase(di);
}

void ObjectAdaptor::return_error(Continuation *ret, const Error error)
{
	ret->_conn.send(ErrorMessage(ret->_call, error.name(), error.message()));

	ContinuationMap::iterator di = _continuations.find(ret->_tag);

	delete di->second;

	_continuations.erase(di);
}

ObjectAdaptor::Continuation *ObjectAdaptor::find_continuation(const Tag *tag)
{
	ContinuationMap::iterator di = _continuations.find(tag);

	return di != _continuations.end() ? di->second : NULL;
}

ObjectAdaptor::Continuation::Continuation(Connection &conn, const CallMessage &call, const Tag *tag)
: _conn(conn), _call(call), _return(_call), _tag(tag)
{
	_writer = _return.writer(); //todo: verify
}

/*
*/

ObjectProxy::ObjectProxy(Connection &conn, const Path &path, const char *service)
: Object(conn, path, service)
{
	register_obj();
}

// TODO(ers@google.com): unregister_obj() makes a synchronous
// dbus method call, which can result in a deadlock if the
// ObjectProxy is deleted while in a callback from a signal
// or a pending call reply.
ObjectProxy::~ObjectProxy()
{
	cancel_pending_calls();
	unregister_obj();
}

void ObjectProxy::cancel_pending_calls()
{
	PendingCallList::const_iterator pi = _pending_calls.begin();
	while (pi != _pending_calls.end())
	{
		(*pi)->cancel();
		delete *pi;
		++pi;
	}
	_pending_calls.clear();
}

void ObjectProxy::_remove_pending_call(PendingCall *pending)
{
	PendingCallList::iterator pi = _pending_calls.begin();
	while (pi != _pending_calls.end())
	{
		if (*pi == pending)
		{
			_pending_calls.erase(pi);
			break;
		}
		++pi;
	}
	delete pending;
}

void ObjectProxy::register_obj()
{
	debug_log("registering remote object %s", path().c_str());

	_filtered = new Callback<ObjectProxy, bool, const Message &>(this, &ObjectProxy::handle_message);

	conn().add_filter(_filtered);

	InterfaceProxyTable::const_iterator ii = _interfaces.begin();
	while (ii != _interfaces.end())
	{
		std::string im = "type='signal',interface='"+ii->first+"',path='"+path()+"'";
		conn().add_match(im.c_str());
		++ii;
	}
}

void ObjectProxy::unregister_obj()
{
	debug_log("unregistering remote object %s", path().c_str());

	InterfaceProxyTable::const_iterator ii = _interfaces.begin();
	while (ii != _interfaces.end())
	{
		std::string im = "type='signal',interface='"+ii->first+"',path='"+path()+"'";
		conn().remove_match(im.c_str());
		++ii;
	}
	conn().remove_filter(_filtered);
}

bool ObjectProxy::is_registered()
{
	return true;
}

Message ObjectProxy::_invoke_method(CallMessage &call)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	return conn().send_blocking(call);
}

bool ObjectProxy::_invoke_method_noreply(CallMessage &call)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	return conn().send(call);
}

PendingCall *ObjectProxy::_invoke_method_async(CallMessage &call, int timeout)
{
	if (call.path() == NULL)
		call.path(path().c_str());

	if (call.destination() == NULL)
		call.destination(service().c_str());

	PendingCall *pending = conn().send_async(call, timeout);
	_pending_calls.push_back(pending);
	return pending;
}

bool ObjectProxy::handle_message(const Message &msg)
{
	switch (msg.type())
	{
		case DBUS_MESSAGE_TYPE_SIGNAL:
		{
			const SignalMessage &smsg = reinterpret_cast<const SignalMessage &>(msg);
			const char *interface	= smsg.interface();
			const char *member	= smsg.member();
			const char *objpath	= smsg.path();

			if (objpath != path()) return false;

			debug_log("filtered signal %s(in %s) from %s to object %s",
				member, interface, msg.sender(), objpath);

			InterfaceProxy *ii = find_interface(interface);
			if (ii)
			{
				return ii->dispatch_signal(smsg);
			}
			else
			{
				return false;
			}
		}
		default:
		{
			return false;
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * 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/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include <deque>
#include <algorithm> // std::min_element
#include <iterator>
#include "registration/transform/rigid.h"
#include "math/gradient_descent.h"
#include "math/math.h"
#include "math/median.h"

namespace MR
{
  using namespace MR::Math;

  namespace Registration
  {
    namespace Transform
    {
      void project_linear2rotation(const Eigen::Matrix<default_type, 3, 3>& linear, Eigen::Matrix<default_type, 3, 3>& rotation) {
        Eigen::JacobiSVD<Eigen::Matrix<default_type, 3, 3>> svd(linear, Eigen::ComputeFullU | Eigen::ComputeFullV);

        default_type x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
        Eigen::Matrix<default_type, 3, 1> sv(svd.singularValues());
        sv.coeffRef(0) *= x;
        Eigen::Matrix<default_type, 3, 3> m(svd.matrixU());
        m.col(0) /= x;
        rotation = m * svd.matrixV().adjoint();
        assert((rotation * rotation.transpose().eval()).isApprox(Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic>::Identity(3,3)) && "project_linear2rotation orthonormal?");
      }

      bool RigidLinearNonSymmetricUpdate::operator() (Eigen::Matrix<default_type, Eigen::Dynamic, 1>& newx,
          const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& x,
          const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& g,
          default_type step_size) {
          assert (newx.size() == 12);
          assert (x.size() == 12);
          assert (g.size() == 12);

          Eigen::Matrix<default_type, 12, 1> delta;
          Eigen::Matrix<default_type, 4, 4> X, Delta, G, A, Asqrt, B, Bsqrt, Bsqrtinv, Xnew, P, Diff;
          Registration::Transform::param_vec2mat(g, G);
          Registration::Transform::param_vec2mat(x, X);

          // enforce updates in the range of small angles
          if (step_size * G.block(0,0,3,3).array().abs().maxCoeff() > 0.2) {
            step_size = 0.2 / G.block(0,0,3,3).array().abs().maxCoeff();
          }
          // use control points and coherence length as update criterion
          if (control_points.size()) {
            P = control_points;
            const default_type orig_step_size(step_size);
            const default_type step_down_factor(0.5);
            while (true) {
              delta = g * step_size;
              Registration::Transform::param_vec2mat(delta, Delta);
              if ((X+Delta).determinant() <= 0.0){ step_size *= step_down_factor; continue; }
              Diff.noalias() = ((X+Delta) * P - X * P).cwiseAbs();
              if ((Diff.template block<3,1>(0,0) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,1) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,2) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,3) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}

              A = X - Delta;
              A(3,3) = 1.0;
              if (A.determinant() <= 0.0){ step_size *= step_down_factor; continue; }

              B = X.inverse() + Delta;
              B(3,3) = 1.0;
              if (B.determinant() <= 0.0){ step_size *= step_down_factor; continue; }

              Asqrt = A.sqrt().eval();
              assert(A.isApprox(Asqrt * Asqrt));
              Bsqrt = B.sqrt().eval();
              assert(B.isApprox(Bsqrt * Bsqrt));
              Bsqrtinv = Bsqrt.inverse().eval();

              Xnew = (Asqrt * Bsqrtinv) - ((Asqrt * Bsqrtinv - Bsqrtinv * Asqrt) * 0.5);
              Diff.noalias() = ((Xnew) * P - X * P).cwiseAbs();
              if ((Diff.template block<3,1>(0,0) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,1) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,2) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,3) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}

              break;
            }
            if (orig_step_size != step_size) { DEBUG("step size changed from " + str(orig_step_size) + " to " + str(step_size)); }
          } else {
            // reduce step size if determinant of matrix becomes negative (happens rarely at first few iterations)
            size_t cnt = 0;
            const default_type factor(0.9);
            while (true) {
              delta = g * step_size;
              Registration::Transform::param_vec2mat(delta, Delta);
              if (Delta.block(0,0,3,3).array().abs().maxCoeff() > 0.1) {
                step_size = 0.09 / G.block(0,0,3,3).array().abs().maxCoeff();
                INFO(str(step_size) + " " + str(g * step_size));
                continue;
              }
              if (Delta.block(0,3,3,1).array().abs().maxCoeff() > 10.0){
                step_size = 9.0 / G.block(0,3,3,1).array().abs().maxCoeff();
                INFO(str(step_size) + " " + str(g * step_size));
                continue;
              }
              A = X - Delta;
              A(3,3) = 1.0;
              if (A.determinant() < 0) {
                step_size *= factor;
                ++cnt;
              } else {
                break;
              }
            }
            if (cnt > 0) INFO("rigid: gradient descent step size was too large. Multiplied by factor "
             + str(std::pow (factor, cnt), 4) + " (now: "+ str(step_size, 4) + ")");

            B = X.inverse() + Delta;
            B(3,3) = 1.0;
            assert(B.determinant() > 0.0);
            Asqrt = A.sqrt().eval();
            assert(A.isApprox(Asqrt * Asqrt));
            Bsqrt = B.sqrt().eval();
            assert(B.isApprox(Bsqrt * Bsqrt));
            Bsqrtinv = Bsqrt.inverse().eval();

            // approximation for symmetry reasons as
            // A and B don't commute
            Xnew = (Asqrt * Bsqrtinv) - ((Asqrt * Bsqrtinv - Bsqrtinv * Asqrt) * 0.5);
          }

          // project affine to rigid
          Eigen::Matrix<default_type, 3, 3> L(Xnew.template block<3,3>(0,0));
          Eigen::Matrix<default_type, 3, 3> R;
          project_linear2rotation(L, R);
          Xnew.template block<3,3>(0,0) = R;
          Registration::Transform::param_mat2vec(Xnew, newx);

          // stop criterion based on max shift of control points
          if (control_points.size()) {
            Diff.row(0) *= recip_spacing(0);
            Diff.row(1) *= recip_spacing(1);
            Diff.row(2) *= recip_spacing(2);
            Diff.colwise() -= stop_len;
            // MAT(Diff);
            if (Diff.template block<3,4>(0,0).maxCoeff() <= 0.0) {
              DEBUG("max control point movement (" + str(Diff.template block<3,4>(0,0).maxCoeff()) +
              ") smaller than tolerance" );
              return false;
            }
          }
// #ifdef REGISTRATION_GRADIENT_DESCENT_DEBUG
//             if (newx.isApprox(x)){
//               ValueType debug = 0;
//               for (ssize_t i=0; i<newx.size(); ++i){
//                 debug += std::abs(newx[i]-x[i]);
//               }
//               INFO("rigid update parameter cumulative change: " + str(debug));
//               VEC(newx);
//               VEC(g);
//               VAR(step_size);
//             }
// #endif
            return !(newx.isApprox(x));
          }

          void RigidLinearNonSymmetricUpdate::set_control_points (
            const Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic>& points,
            const Eigen::Vector3d& coherence_dist,
            const Eigen::Vector3d& stop_length,
            const Eigen::Vector3d& voxel_spacing ) {
            assert(points.rows() == 4);
            assert(points.cols() == 4);
            control_points = points;
            coherence_distance = coherence_dist;
            stop_len << stop_length, 0.0;
            recip_spacing << voxel_spacing.cwiseInverse(), 1.0;
          }

          bool RigidRobustEstimator::operator() (Eigen::Matrix<default_type, Eigen::Dynamic, 1>& newx,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& x,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& g,
            default_type step_size) {
          assert (newx.size() == x.size());
          assert (g.size() == x.size());
          newx = x - step_size * g;
          return !(newx.isApprox(x));
          }

      /** \addtogroup Transforms
      @{ */

      /*! A 3D rigid transformation class for registration.
       *
       * This class supports the ability to define the centre of rotation.
       * This should be set prior to commencing registration based on the centre of the target image.
       * The translation also should be initialised as moving image centre minus the target image centre.
       *
       */

          Eigen::Matrix<default_type, 4, 1> Rigid::get_jacobian_vector_wrt_params (const Eigen::Vector3& p) const {
            Eigen::Matrix<default_type, 4, 1> jac;
            jac.head(3) = p - centre;
            jac(3) = 1.0;
            return jac;
          }

          Eigen::MatrixXd Rigid::get_jacobian_wrt_params (const Eigen::Vector3& p) const {
            Eigen::MatrixXd jacobian (3, 12);
            jacobian.setZero();
            const auto v = get_jacobian_vector_wrt_params(p);
            jacobian.block<1, 4>(0, 0) = v;
            jacobian.block<1, 4>(1, 4) = v;
            jacobian.block<1, 4>(2, 8) = v;
            return jacobian;
          }

          void Rigid::set_parameter_vector (const Eigen::Matrix<Rigid::ParameterType, Eigen::Dynamic, 1>& param_vector) {
            this->trafo.matrix() = Eigen::Map<const Eigen::Matrix<ParameterType, 3, 4, Eigen::RowMajor> >(&param_vector(0));
            this->compute_halfspace_transformations();
          }

          void Rigid::get_parameter_vector (Eigen::Matrix<Rigid::ParameterType, Eigen::Dynamic, 1>& param_vector) const {
            param_vector.resize (12);
            param_mat2vec (this->trafo.matrix(), param_vector);
          }

          bool Rigid::robust_estimate (
            Eigen::Matrix<default_type, Eigen::Dynamic, 1>& gradient,
            std::vector<Eigen::Matrix<default_type, Eigen::Dynamic, 1>>& grad_estimates,
            const Eigen::Matrix<default_type, 4, 4>& control_points,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& parameter_vector,
            const default_type& weiszfeld_precision = 1.0e-6,
            const size_t& weiszfeld_iterations = 1000,
            default_type learning_rate = 1.0) const {
            throw Exception ("TODO robust estimate");
          }

      //! @}
    }
  }
}

<commit_msg>registration: rigid transformation projection conserves centre of control points<commit_after>/*
 * Copyright (c) 2008-2016 the MRtrix3 contributors
 *
 * 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/
 *
 * MRtrix 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.
 *
 * For more details, see www.mrtrix.org
 *
 */

#include <deque>
#include <algorithm> // std::min_element
#include <iterator>
#include "registration/transform/rigid.h"
#include "math/gradient_descent.h"
#include "math/math.h"
#include "math/median.h"
#include "debug.h"

namespace MR
{
  using namespace MR::Math;

  namespace Registration
  {
    namespace Transform
    {
      void project_linear2rotation(const Eigen::Matrix<default_type, 3, 3>& linear, Eigen::Matrix<default_type, 3, 3>& rotation) {
        Eigen::JacobiSVD<Eigen::Matrix<default_type, 3, 3>> svd(linear, Eigen::ComputeFullU | Eigen::ComputeFullV);

        default_type x = (svd.matrixU() * svd.matrixV().adjoint()).determinant(); // so x has absolute value 1
        Eigen::Matrix<default_type, 3, 1> sv(svd.singularValues());
        sv.coeffRef(0) *= x;
        Eigen::Matrix<default_type, 3, 3> m(svd.matrixU());
        m.col(0) /= x;
        rotation = m * svd.matrixV().adjoint();
        assert((rotation * rotation.transpose().eval()).isApprox(Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic>::Identity(3,3)) && "project_linear2rotation orthonormal?");
      }

      bool RigidLinearNonSymmetricUpdate::operator() (Eigen::Matrix<default_type, Eigen::Dynamic, 1>& newx,
          const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& x,
          const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& g,
          default_type step_size) {
          assert (newx.size() == 12);
          assert (x.size() == 12);
          assert (g.size() == 12);

          Eigen::Matrix<default_type, 12, 1> delta;
          Eigen::Matrix<default_type, 4, 4> X, Delta, G, A, Asqrt, B, Bsqrt, Bsqrtinv, Xnew, P, Diff;
          Registration::Transform::param_vec2mat(g, G);
          Registration::Transform::param_vec2mat(x, X);

          // enforce updates in the range of small angles
          if (step_size * G.block(0,0,3,3).array().abs().maxCoeff() > 0.2) {
            step_size = 0.2 / G.block(0,0,3,3).array().abs().maxCoeff();
          }
          // use control points and coherence length as update criterion
          if (control_points.size()) {
            P = control_points;
            const default_type orig_step_size(step_size);
            const default_type step_down_factor(0.5);
            while (true) {
              delta = g * step_size;
              Registration::Transform::param_vec2mat(delta, Delta);
              if ((X+Delta).determinant() <= 0.0){ step_size *= step_down_factor; continue; }
              Diff.noalias() = ((X+Delta) * P - X * P).cwiseAbs();
              if ((Diff.template block<3,1>(0,0) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,1) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,2) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,3) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}

              A = X - Delta;
              A(3,3) = 1.0;
              if (A.determinant() <= 0.0){ step_size *= step_down_factor; continue; }

              B = X.inverse() + Delta;
              B(3,3) = 1.0;
              if (B.determinant() <= 0.0){ step_size *= step_down_factor; continue; }

              Asqrt = A.sqrt().eval();
              assert(A.isApprox(Asqrt * Asqrt));
              Bsqrt = B.sqrt().eval();
              assert(B.isApprox(Bsqrt * Bsqrt));
              Bsqrtinv = Bsqrt.inverse().eval();

              Xnew = (Asqrt * Bsqrtinv) - ((Asqrt * Bsqrtinv - Bsqrtinv * Asqrt) * 0.5);
              Diff.noalias() = ((Xnew) * P - X * P).cwiseAbs();
              if ((Diff.template block<3,1>(0,0) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,1) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,2) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}
              if ((Diff.template block<3,1>(0,3) - coherence_distance).maxCoeff() > 0.0) { step_size *= step_down_factor; continue;}

              break;
            }
            if (orig_step_size != step_size) { DEBUG("step size changed from " + str(orig_step_size) + " to " + str(step_size)); }
          } else {
            // reduce step size if determinant of matrix becomes negative (happens rarely at first few iterations)
            size_t cnt = 0;
            const default_type factor(0.9);
            while (true) {
              delta = g * step_size;
              Registration::Transform::param_vec2mat(delta, Delta);
              if (Delta.block(0,0,3,3).array().abs().maxCoeff() > 0.1) {
                step_size = 0.09 / G.block(0,0,3,3).array().abs().maxCoeff();
                INFO(str(step_size) + " " + str(g * step_size));
                continue;
              }
              if (Delta.block(0,3,3,1).array().abs().maxCoeff() > 10.0){
                step_size = 9.0 / G.block(0,3,3,1).array().abs().maxCoeff();
                INFO(str(step_size) + " " + str(g * step_size));
                continue;
              }
              A = X - Delta;
              A(3,3) = 1.0;
              if (A.determinant() < 0) {
                step_size *= factor;
                ++cnt;
              } else {
                break;
              }
            }
            if (cnt > 0) INFO("rigid: gradient descent step size was too large. Multiplied by factor "
             + str(std::pow (factor, cnt), 4) + " (now: "+ str(step_size, 4) + ")");

            B = X.inverse() + Delta;
            B(3,3) = 1.0;
            assert(B.determinant() > 0.0);
            Asqrt = A.sqrt().eval();
            assert(A.isApprox(Asqrt * Asqrt));
            Bsqrt = B.sqrt().eval();
            assert(B.isApprox(Bsqrt * Bsqrt));
            Bsqrtinv = Bsqrt.inverse().eval();

            // approximation for symmetry reasons as
            // A and B don't commute
            Xnew = (Asqrt * Bsqrtinv) - ((Asqrt * Bsqrtinv - Bsqrtinv * Asqrt) * 0.5);
          }

          // project affine 3x3 matrix to rigid matrix
          // adjust translation to account for scale of affine by matching projected control point
          // centroids of affine and projected rigid transformation
          Eigen::Matrix<default_type, 3, 3> L(Xnew.template block<3,3>(0,0));
          Eigen::Matrix<default_type, 3, 3> R;
          project_linear2rotation(L, R);
          Xnew.template block<3,3>(0,0) = R;
          if (control_points.size()) {
            P = control_points;
            Eigen::Matrix<default_type, 3, 1> T_affine, T_new, centroid;
            T_affine = Xnew.block<3,1>(0,3);
            centroid = P.rowwise().mean().head<3>();
            T_new = L.sqrt() * centroid + T_affine - R.sqrt() * centroid;
            Xnew.template block<3,1>(0,3) = T_new;
          }
          Registration::Transform::param_mat2vec(Xnew, newx);

          // stop criterion based on max shift of control points
          if (control_points.size()) {
            Diff.noalias() = ((Xnew) * P - X * P).cwiseAbs();
            Diff.row(0) *= recip_spacing(0);
            Diff.row(1) *= recip_spacing(1);
            Diff.row(2) *= recip_spacing(2);
            Diff.colwise() -= stop_len;
            if (Diff.template block<3,4>(0,0).maxCoeff() <= 0.0) {
              DEBUG("max control point movement (" + str(Diff.template block<3,4>(0,0).maxCoeff()) +
              ") smaller than tolerance" );
              return false;
            }
          }
// #ifdef REGISTRATION_GRADIENT_DESCENT_DEBUG
//             if (newx.isApprox(x)){
//               ValueType debug = 0;
//               for (ssize_t i=0; i<newx.size(); ++i){
//                 debug += std::abs(newx[i]-x[i]);
//               }
//               INFO("rigid update parameter cumulative change: " + str(debug));
//               VEC(newx);
//               VEC(g);
//               VAR(step_size);
//             }
// #endif
            return !(newx.isApprox(x));
          }

          void RigidLinearNonSymmetricUpdate::set_control_points (
            const Eigen::Matrix<default_type, Eigen::Dynamic, Eigen::Dynamic>& points,
            const Eigen::Vector3d& coherence_dist,
            const Eigen::Vector3d& stop_length,
            const Eigen::Vector3d& voxel_spacing ) {
            assert(points.rows() == 4);
            assert(points.cols() == 4);
            control_points = points;
            coherence_distance = coherence_dist;
            stop_len << stop_length, 0.0;
            recip_spacing << voxel_spacing.cwiseInverse(), 1.0;
          }

          bool RigidRobustEstimator::operator() (Eigen::Matrix<default_type, Eigen::Dynamic, 1>& newx,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& x,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& g,
            default_type step_size) {
          assert (newx.size() == x.size());
          assert (g.size() == x.size());
          newx = x - step_size * g;
          return !(newx.isApprox(x));
          }

      /** \addtogroup Transforms
      @{ */

      /*! A 3D rigid transformation class for registration.
       *
       * This class supports the ability to define the centre of rotation.
       * This should be set prior to commencing registration based on the centre of the target image.
       * The translation also should be initialised as moving image centre minus the target image centre.
       *
       */

          Eigen::Matrix<default_type, 4, 1> Rigid::get_jacobian_vector_wrt_params (const Eigen::Vector3& p) const {
            Eigen::Matrix<default_type, 4, 1> jac;
            jac.head(3) = p - centre;
            jac(3) = 1.0;
            return jac;
          }

          Eigen::MatrixXd Rigid::get_jacobian_wrt_params (const Eigen::Vector3& p) const {
            Eigen::MatrixXd jacobian (3, 12);
            jacobian.setZero();
            const auto v = get_jacobian_vector_wrt_params(p);
            jacobian.block<1, 4>(0, 0) = v;
            jacobian.block<1, 4>(1, 4) = v;
            jacobian.block<1, 4>(2, 8) = v;
            return jacobian;
          }

          void Rigid::set_parameter_vector (const Eigen::Matrix<Rigid::ParameterType, Eigen::Dynamic, 1>& param_vector) {
            this->trafo.matrix() = Eigen::Map<const Eigen::Matrix<ParameterType, 3, 4, Eigen::RowMajor> >(&param_vector(0));
            this->compute_halfspace_transformations();
          }

          void Rigid::get_parameter_vector (Eigen::Matrix<Rigid::ParameterType, Eigen::Dynamic, 1>& param_vector) const {
            param_vector.resize (12);
            param_mat2vec (this->trafo.matrix(), param_vector);
          }

          bool Rigid::robust_estimate (
            Eigen::Matrix<default_type, Eigen::Dynamic, 1>& gradient,
            std::vector<Eigen::Matrix<default_type, Eigen::Dynamic, 1>>& grad_estimates,
            const Eigen::Matrix<default_type, 4, 4>& control_points,
            const Eigen::Matrix<default_type, Eigen::Dynamic, 1>& parameter_vector,
            const default_type& weiszfeld_precision = 1.0e-6,
            const size_t& weiszfeld_iterations = 1000,
            default_type learning_rate = 1.0) const {
            throw Exception ("TODO robust estimate");
          }

      //! @}
    }
  }
}

<|endoftext|>


<commit_before>// -------------------------------------------------------------------
//
// Copyright (c) 2007-2012 Basho Technologies, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#ifndef LOCKFREE_QUEUE_HPP_
#define LOCKFREE_QUEUE_HPP_

#include <cstddef>
#include <cstdio>
#include <boost/atomic.hpp>

// specialize this for queue item types to calculate total byte size of queue
template <typename T> std::size_t item_size(T item) { return sizeof(item); }

template <typename T, size_t size=1000000>
class lockfree_queue
{
    typedef T item_type;
    typedef std::size_t index_type;

    struct slot
    {
         item_type item;
         boost::atomic_bool used;
    };

    slot storage_[size];
    std::size_t read_, write_;
    boost::atomic_ulong len_, byte_size_;
public: // construction
     lockfree_queue()
         : read_(0),
           write_(0),
           len_(0),
           byte_size_(0)
     {
         for (std::size_t i=0; i < size; i++)
             array_[i].used = false;
     }
public:  // api
    bool produce(const T& t)
    {
        T* item = write_prepare();
        if (!item)
            return false;
        *item = t;
        write_publish();
        return true;
    }

    bool consume(T& result)
    {
        T* item = read_fetch();
        if (!item)
            return false;
        result = *item;
        read_consume();
        return true;
    }

    std::size_t len() const
    {
        return len_.load(boost::memory_order_consume);
    }

    std::size_t byte_size() const
    {
        return byte_size_.load(boost::memory_order_consume);
    }
protected: // fetch / publish primitives
    T* read_fetch()
    {
        index_type rd = read_;
        slot* p = &(array_[rd % size]);
        if (! p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void read_consume()
    {
        index_type rd = read_;
        slot *p = &(array_[rd % size]);
        p->used.store(false, boost::memory_order_release);
        len_.fetch_sub(1, boost::memory_order_release);
        byte_size_.fetch_sub(item_size(p->item), boost::memory_order_release);
        read_++;
    }

    T* write_prepare()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        if (p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void write_publish()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        p->used.store(true, boost::memory_order_release);
        len_.fetch_add(1, boost::memory_order_release);
        byte_size_.fetch_add(item_size(p->item), boost::memory_order_release);
        write_++;
    }

private: // noncopyable
    lockfree_queue( const lockfree_queue& );
    const lockfree_queue& operator=( const lockfree_queue& );
};

#endif // include guard
<commit_msg>bad search/replace<commit_after>// -------------------------------------------------------------------
//
// Copyright (c) 2007-2012 Basho Technologies, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#ifndef LOCKFREE_QUEUE_HPP_
#define LOCKFREE_QUEUE_HPP_

#include <cstddef>
#include <cstdio>
#include <boost/atomic.hpp>

// specialize this for queue item types to calculate total byte size of queue
template <typename T> std::size_t item_size(T item) { return sizeof(item); }

template <typename T, size_t size=1000000>
class lockfree_queue
{
    typedef T item_type;
    typedef std::size_t index_type;

    struct slot
    {
         item_type item;
         boost::atomic_bool used;
    };

    slot storage_[size];
    std::size_t read_, write_;
    boost::atomic_ulong len_, byte_size_;
public: // construction
     lockfree_queue()
         : read_(0),
           write_(0),
           len_(0),
           byte_size_(0)
     {
         for (std::size_t i=0; i < size; i++)
             storage_[i].used = false;
     }
public:  // api
    bool produce(const T& t)
    {
        T* item = write_prepare();
        if (!item)
            return false;
        *item = t;
        write_publish();
        return true;
    }

    bool consume(T& result)
    {
        T* item = read_fetch();
        if (!item)
            return false;
        result = *item;
        read_consume();
        return true;
    }

    std::size_t len() const
    {
        return len_.load(boost::memory_order_consume);
    }

    std::size_t byte_size() const
    {
        return byte_size_.load(boost::memory_order_consume);
    }
protected: // fetch / publish primitives
    T* read_fetch()
    {
        index_type rd = read_;
        slot* p = &(storage_[rd % size]);
        if (! p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void read_consume()
    {
        index_type rd = read_;
        slot *p = &(storage_[rd % size]);
        p->used.store(false, boost::memory_order_release);
        len_.fetch_sub(1, boost::memory_order_release);
        byte_size_.fetch_sub(item_size(p->item), boost::memory_order_release);
        read_++;
    }

    T* write_prepare()
    {
        index_type wr = write_;
        slot *p = &(storage_[wr % size]);
        if (p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void write_publish()
    {
        index_type wr = write_;
        slot *p = &(storage_[wr % size]);
        p->used.store(true, boost::memory_order_release);
        len_.fetch_add(1, boost::memory_order_release);
        byte_size_.fetch_add(item_size(p->item), boost::memory_order_release);
        write_++;
    }

private: // noncopyable
    lockfree_queue( const lockfree_queue& );
    const lockfree_queue& operator=( const lockfree_queue& );
};

#endif // include guard
<|endoftext|>


<commit_before>// -------------------------------------------------------------------
//
// Copyright (c) 2007-2012 Basho Technologies, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#ifndef LOCKFREE_QUEUE_HPP_
#define LOCKFREE_QUEUE_HPP_

#include <cstddef>
#include <cstdio>
#include <boost/atomic.hpp>

// specialize this for queue item types to calculate total byte size of queue
template <typename T> std::size_t item_size(T item) { return sizeof(item); }

template <typename T, size_t size=1000000>
class lockfree_queue
{
    typedef T item_type;
    typedef int index_type;

    struct slot
    {
         item_type item;
         boost::atomic_bool used;
    };
    slot array_[size];
    int  read_, write_;
    boost::atomic_ulong len_, byte_size_;
public: // construction
     lockfree_queue()
         : read_(0),
           write_(0),
           len_(0),
           byte_size_(0)
     {
         for (std::size_t i=0; i < size; i++)
             array_[i].used = false;
     }
public:  // api
    bool produce(const T& t)
    {
        T* item = write_prepare();
        if (!item)
            return false;
        *item = t;
        write_publish();
        return true;
    }

    bool consume(T& result)
    {
        T* item = read_fetch();
        if (!item)
            return false;
        result = *item;
        read_consume();
        return true;
    }

    std::size_t len() const
    {
        return len_.load(boost::memory_order_consume);
    }

    std::size_t byte_size() const
    {
        return byte_size_.load(boost::memory_order_consume);
    }
protected: // fetch / publish primitives
    T* read_fetch()
    {
        index_type rd = read_;
        slot* p = &(array_[rd % size]);
        if (! p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void read_consume()
    {
        index_type rd = read_;
        slot *p = &(array_[rd % size]);
        p->used.store(false, boost::memory_order_release);
        len_.fetch_sub(1, boost::memory_order_release);
        byte_size_.fetch_sub(item_size(p->item), boost::memory_order_release);
        read_++;
    }

    T* write_prepare()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        if (p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void write_publish()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        p->used.store(true, boost::memory_order_release);
        len_.fetch_add(1, boost::memory_order_release);
        byte_size_.fetch_add(item_size(p->item), boost::memory_order_release);
        write_++;
    }

private: // noncopyable
    lockfree_queue( const lockfree_queue& );
    const lockfree_queue& operator=( const lockfree_queue& );
};

#endif // include guard
<commit_msg>use size_t for read, write indexes<commit_after>// -------------------------------------------------------------------
//
// Copyright (c) 2007-2012 Basho Technologies, Inc. All Rights Reserved.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#ifndef LOCKFREE_QUEUE_HPP_
#define LOCKFREE_QUEUE_HPP_

#include <cstddef>
#include <cstdio>
#include <boost/atomic.hpp>

// specialize this for queue item types to calculate total byte size of queue
template <typename T> std::size_t item_size(T item) { return sizeof(item); }

template <typename T, size_t size=1000000>
class lockfree_queue
{
    typedef T item_type;
    typedef std::size_t index_type;

    struct slot
    {
         item_type item;
         boost::atomic_bool used;
    };

    slot storage_[size];
    std::size_t read_, write_;
    boost::atomic_ulong len_, byte_size_;
public: // construction
     lockfree_queue()
         : read_(0),
           write_(0),
           len_(0),
           byte_size_(0)
     {
         for (std::size_t i=0; i < size; i++)
             array_[i].used = false;
     }
public:  // api
    bool produce(const T& t)
    {
        T* item = write_prepare();
        if (!item)
            return false;
        *item = t;
        write_publish();
        return true;
    }

    bool consume(T& result)
    {
        T* item = read_fetch();
        if (!item)
            return false;
        result = *item;
        read_consume();
        return true;
    }

    std::size_t len() const
    {
        return len_.load(boost::memory_order_consume);
    }

    std::size_t byte_size() const
    {
        return byte_size_.load(boost::memory_order_consume);
    }
protected: // fetch / publish primitives
    T* read_fetch()
    {
        index_type rd = read_;
        slot* p = &(array_[rd % size]);
        if (! p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void read_consume()
    {
        index_type rd = read_;
        slot *p = &(array_[rd % size]);
        p->used.store(false, boost::memory_order_release);
        len_.fetch_sub(1, boost::memory_order_release);
        byte_size_.fetch_sub(item_size(p->item), boost::memory_order_release);
        read_++;
    }

    T* write_prepare()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        if (p->used.load(boost::memory_order_acquire))
            return 0;
        return &(p->item);
    }

    void write_publish()
    {
        index_type wr = write_;
        slot *p = &(array_[wr % size]);
        p->used.store(true, boost::memory_order_release);
        len_.fetch_add(1, boost::memory_order_release);
        byte_size_.fetch_add(item_size(p->item), boost::memory_order_release);
        write_++;
    }

private: // noncopyable
    lockfree_queue( const lockfree_queue& );
    const lockfree_queue& operator=( const lockfree_queue& );
};

#endif // include guard
<|endoftext|>