<commit_before>/*************************************************************************
 *
 *  $RCSfile: proplinelistener.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-25 16:03:58 $
 *
 *  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 EXPRESS 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 _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    class IPropertyLineListener
    {
    public:
        virtual void    Modified(   const String& _rName, const String& _rVal, void* _pData) = 0;
        virtual void    Clicked(    const String& _rName, const String& _rVal, void* _pData) = 0;
        virtual void    Commit(     const String& _rName, const String& _rVal, void* _pData) = 0;
        virtual void    Select(     const String& _rName, void* _pData) = 0;
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_

<commit_msg>INTEGRATION: CWS eforms2 (1.2.156); FILE MERGED 2004/04/26 11:37:10 fs 1.2.156.1: some cleanup/consolidation<commit_after>/*************************************************************************
 *
 *  $RCSfile: proplinelistener.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-16 12:11:55 $
 *
 *  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 EXPRESS 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 _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_
#define _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    class IPropertyLineListener
    {
    public:
        virtual void    Modified(   const String& _rName, const String& _rVal ) = 0;
        virtual void    Clicked(    const String& _rName, sal_uInt16 _nFlags, bool _bPrimary ) = 0;
        virtual void    Commit(     const String& _rName, const String& _rVal ) = 0;
    };

//............................................................................
} // namespace pcr
//............................................................................

#endif // _EXTENSIONS_PROPCTRLR_PROPLINELISTENER_HXX_

<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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.
 */

#include "runtime_support_builder.h"

#include "gc/card_table.h"
#include "ir_builder.h"
#include "monitor.h"
#include "object.h"
#include "thread.h"

#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Type.h>

using namespace llvm;

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

RuntimeSupportBuilder::RuntimeSupportBuilder(llvm::LLVMContext& context,
                                             llvm::Module& module,
                                             IRBuilder& irb)
    : context_(context), module_(module), irb_(irb)
{
  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
  do { \
    llvm::Function* fn = module_.getFunction(#NAME); \
    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
    runtime_support_func_decls_[runtime_support::ID] = fn; \
  } while (0);

#include "runtime_support_func_list.h"
  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}

/* Thread */

llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  CallInst* call_inst = irb_.CreateCall(func);
  call_inst->setOnlyReadsMemory();
  irb_.SetTBAA(call_inst, kTBAAConstJObject);
  return call_inst;
}

llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
                                                             TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}

void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
                                                    TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}

llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) {
  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
  return irb_.CreateCall(func, thread);
}

/* ShadowFrame */

llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                                        llvm::Value* method,
                                                        uint32_t num_vregs) {
  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                     irb_.getArtFrameTy()->getPointerTo(),
                                                     kTBAARuntimeInfo);
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          new_shadow_frame,
                          kTBAARuntimeInfo);

  // Store the method pointer
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::MethodOffset(),
                           method,
                           kTBAAShadowFrame);

  // Store the number of vregs
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::NumberOfVRegsOffset(),
                           irb_.getInt32(num_vregs),
                           kTBAAShadowFrame);

  // Store the link to previous shadow frame
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::LinkOffset(),
                           old_shadow_frame,
                           kTBAAShadowFrame);

  return old_shadow_frame;
}

llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
                                                   llvm::Value* method,
                                                   uint32_t num_vregs) {
  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
  llvm::CallInst* call_inst =
      irb_.CreateCall4(func,
                       EmitGetCurrentThread(),
                       new_shadow_frame,
                       method,
                       irb_.getInt32(num_vregs));
  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
  return call_inst;
}

void RuntimeSupportBuilder::EmitPopShadowFrame(llvm::Value* old_shadow_frame) {
  // Store old shadow frame to TopShadowFrame
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          old_shadow_frame,
                          kTBAARuntimeInfo);
}

/* Exception */

llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
}

llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
  Value* state_and_flags = EmitLoadFromThreadOffset(Thread::ThreadFlagsOffset().Int32Value(),
                                                    irb_.getInt16Ty(),
                                                    kTBAARuntimeInfo);
  // Mask exception pending status and return true if non-zero.
  Value* exception_pending = irb_.CreateAnd(state_and_flags, irb_.getInt16(kExceptionPending));
  return irb_.CreateICmpNE(exception_pending, irb_.getInt16(0));
}

/* Suspend */

void RuntimeSupportBuilder::EmitTestSuspend() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
  irb_.SetTBAA(call_inst, kTBAAJRuntime);
}

/* Monitor */

void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
  // TODO: Implement a fast path.
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
}

void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getJIntTy(),
                               kTBAARuntimeInfo);
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, held by us and not recursively acquired
  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);
  // Set all bits to zero (except hash state)
  irb_.StoreToObjectOffset(object,
                           Object::MonitorOffset().Int32Value(),
                           hash_state,
                           kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);

  llvm::Value* not_null = irb_.CreateIsNotNull(value);
  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);

  irb_.SetInsertPoint(bb_mark_gc_card);
  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
                                               irb_.getInt8Ty()->getPointerTo(),
                                               kTBAAConstJObject);
  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
  Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(CardTable::kCardShift));
  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
  irb_.CreateStore(irb_.getInt8(CardTable::kCardDirty), card_table_entry, kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

} // namespace compiler_llvm
} // namespace art
<commit_msg>Revert "Change LLVM check for pending exception to use thread flags."<commit_after>/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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.
 */

#include "runtime_support_builder.h"

#include "gc/card_table.h"
#include "ir_builder.h"
#include "monitor.h"
#include "object.h"
#include "thread.h"

#include <llvm/DerivedTypes.h>
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Type.h>

using namespace llvm;

namespace art {
namespace compiler_llvm {

using namespace runtime_support;

RuntimeSupportBuilder::RuntimeSupportBuilder(llvm::LLVMContext& context,
                                             llvm::Module& module,
                                             IRBuilder& irb)
    : context_(context), module_(module), irb_(irb)
{
  memset(target_runtime_support_func_, 0, sizeof(target_runtime_support_func_));
#define GET_RUNTIME_SUPPORT_FUNC_DECL(ID, NAME) \
  do { \
    llvm::Function* fn = module_.getFunction(#NAME); \
    DCHECK_NE(fn, (void*)NULL) << "Function not found: " << #NAME; \
    runtime_support_func_decls_[runtime_support::ID] = fn; \
  } while (0);

#include "runtime_support_func_list.h"
  RUNTIME_SUPPORT_FUNC_LIST(GET_RUNTIME_SUPPORT_FUNC_DECL)
#undef RUNTIME_SUPPORT_FUNC_LIST
#undef GET_RUNTIME_SUPPORT_FUNC_DECL
}

/* Thread */

llvm::Value* RuntimeSupportBuilder::EmitGetCurrentThread() {
  Function* func = GetRuntimeSupportFunction(runtime_support::GetCurrentThread);
  CallInst* call_inst = irb_.CreateCall(func);
  call_inst->setOnlyReadsMemory();
  irb_.SetTBAA(call_inst, kTBAAConstJObject);
  return call_inst;
}

llvm::Value* RuntimeSupportBuilder::EmitLoadFromThreadOffset(int64_t offset, llvm::Type* type,
                                                             TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  return irb_.LoadFromObjectOffset(thread, offset, type, s_ty);
}

void RuntimeSupportBuilder::EmitStoreToThreadOffset(int64_t offset, llvm::Value* value,
                                                    TBAASpecialType s_ty) {
  Value* thread = EmitGetCurrentThread();
  irb_.StoreToObjectOffset(thread, offset, value, s_ty);
}

llvm::Value* RuntimeSupportBuilder::EmitSetCurrentThread(llvm::Value* thread) {
  Function* func = GetRuntimeSupportFunction(runtime_support::SetCurrentThread);
  return irb_.CreateCall(func, thread);
}

/* ShadowFrame */

llvm::Value* RuntimeSupportBuilder::EmitPushShadowFrame(llvm::Value* new_shadow_frame,
                                                        llvm::Value* method,
                                                        uint32_t num_vregs) {
  Value* old_shadow_frame = EmitLoadFromThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                                                     irb_.getArtFrameTy()->getPointerTo(),
                                                     kTBAARuntimeInfo);
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          new_shadow_frame,
                          kTBAARuntimeInfo);

  // Store the method pointer
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::MethodOffset(),
                           method,
                           kTBAAShadowFrame);

  // Store the number of vregs
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::NumberOfVRegsOffset(),
                           irb_.getInt32(num_vregs),
                           kTBAAShadowFrame);

  // Store the link to previous shadow frame
  irb_.StoreToObjectOffset(new_shadow_frame,
                           ShadowFrame::LinkOffset(),
                           old_shadow_frame,
                           kTBAAShadowFrame);

  return old_shadow_frame;
}

llvm::Value*
RuntimeSupportBuilder::EmitPushShadowFrameNoInline(llvm::Value* new_shadow_frame,
                                                   llvm::Value* method,
                                                   uint32_t num_vregs) {
  Function* func = GetRuntimeSupportFunction(runtime_support::PushShadowFrame);
  llvm::CallInst* call_inst =
      irb_.CreateCall4(func,
                       EmitGetCurrentThread(),
                       new_shadow_frame,
                       method,
                       irb_.getInt32(num_vregs));
  irb_.SetTBAA(call_inst, kTBAARuntimeInfo);
  return call_inst;
}

void RuntimeSupportBuilder::EmitPopShadowFrame(llvm::Value* old_shadow_frame) {
  // Store old shadow frame to TopShadowFrame
  EmitStoreToThreadOffset(Thread::TopShadowFrameOffset().Int32Value(),
                          old_shadow_frame,
                          kTBAARuntimeInfo);
}

/* Exception */

llvm::Value* RuntimeSupportBuilder::EmitGetAndClearException() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::GetAndClearException);
  return irb_.CreateCall(slow_func, EmitGetCurrentThread());
}

llvm::Value* RuntimeSupportBuilder::EmitIsExceptionPending() {
  Value* exception = EmitLoadFromThreadOffset(Thread::ExceptionOffset().Int32Value(),
                                              irb_.getJObjectTy(),
                                              kTBAARuntimeInfo);
  // If exception not null
  return irb_.CreateIsNotNull(exception);
}

/* Suspend */

void RuntimeSupportBuilder::EmitTestSuspend() {
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::TestSuspend);
  CallInst* call_inst = irb_.CreateCall(slow_func, EmitGetCurrentThread());
  irb_.SetTBAA(call_inst, kTBAAJRuntime);
}

/* Monitor */

void RuntimeSupportBuilder::EmitLockObject(llvm::Value* object) {
  // TODO: Implement a fast path.
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::LockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
}

void RuntimeSupportBuilder::EmitUnlockObject(llvm::Value* object) {
  Value* lock_id =
      EmitLoadFromThreadOffset(Thread::ThinLockIdOffset().Int32Value(),
                               irb_.getJIntTy(),
                               kTBAARuntimeInfo);
  Value* monitor =
      irb_.LoadFromObjectOffset(object,
                                Object::MonitorOffset().Int32Value(),
                                irb_.getJIntTy(),
                                kTBAARuntimeInfo);

  Value* my_monitor = irb_.CreateShl(lock_id, LW_LOCK_OWNER_SHIFT);
  Value* hash_state = irb_.CreateAnd(monitor, (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
  Value* real_monitor = irb_.CreateAnd(monitor, ~(LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));

  // Is thin lock, held by us and not recursively acquired
  Value* is_fast_path = irb_.CreateICmpEQ(real_monitor, my_monitor);

  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_fast = BasicBlock::Create(context_, "unlock_fast", parent_func);
  BasicBlock* bb_slow = BasicBlock::Create(context_, "unlock_slow", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "unlock_cont", parent_func);
  irb_.CreateCondBr(is_fast_path, bb_fast, bb_slow, kLikely);

  irb_.SetInsertPoint(bb_fast);
  // Set all bits to zero (except hash state)
  irb_.StoreToObjectOffset(object,
                           Object::MonitorOffset().Int32Value(),
                           hash_state,
                           kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_slow);
  Function* slow_func = GetRuntimeSupportFunction(runtime_support::UnlockObject);
  irb_.CreateCall2(slow_func, object, EmitGetCurrentThread());
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

void RuntimeSupportBuilder::EmitMarkGCCard(llvm::Value* value, llvm::Value* target_addr) {
  Function* parent_func = irb_.GetInsertBlock()->getParent();
  BasicBlock* bb_mark_gc_card = BasicBlock::Create(context_, "mark_gc_card", parent_func);
  BasicBlock* bb_cont = BasicBlock::Create(context_, "mark_gc_card_cont", parent_func);

  llvm::Value* not_null = irb_.CreateIsNotNull(value);
  irb_.CreateCondBr(not_null, bb_mark_gc_card, bb_cont);

  irb_.SetInsertPoint(bb_mark_gc_card);
  Value* card_table = EmitLoadFromThreadOffset(Thread::CardTableOffset().Int32Value(),
                                               irb_.getInt8Ty()->getPointerTo(),
                                               kTBAAConstJObject);
  Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
  Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(CardTable::kCardShift));
  Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
  irb_.CreateStore(irb_.getInt8(CardTable::kCardDirty), card_table_entry, kTBAARuntimeInfo);
  irb_.CreateBr(bb_cont);

  irb_.SetInsertPoint(bb_cont);
}

} // namespace compiler_llvm
} // namespace art
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AppTitleWindow.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 14:22:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#ifndef DBAUI_TITLE_WINDOW_HXX
#define DBAUI_TITLE_WINDOW_HXX

#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif

namespace dbaui
{
    class OTitleWindow : public Window
    {
        FixedText   m_aSpace1;
        FixedText   m_aSpace2;
        FixedText   m_aTitle;
        Window*     m_pChild;
        BOOL        m_bShift;
        void ImplInitSettings( BOOL bFont, BOOL bForeground, BOOL bBackground );
    protected:
        virtual void DataChanged(const DataChangedEvent& rDCEvt);
    public:
        OTitleWindow(Window* _pParent,USHORT _nTitleId,WinBits _nBits,BOOL _bShift = TRUE);
        virtual ~OTitleWindow();

        // window overloads
        virtual void Resize();
        virtual void GetFocus();

        /** sets the child window which should be displayed below the title. It will be destroyed at the end.
            @param  _pChild
                The child window.
        */
        void setChildWindow(Window* _pChild);

        /** gets the child window.

            @return
                The child winodw.
        */
        inline Window* getChildWindow() const { return m_pChild; }

        /** sets the title text out of the resource
            @param  _nTitleId
                The resource id of the title text.
        */
        void setTitle(USHORT _nTitleId);

        /** Gets the min Width in Pixel which is needed to display the whole

            @return
                the min width
        */
        long GetWidthPixel() const;
    };
// .............................................................
} // namespace dbaui
// .............................................................
#endif // DBAUI_TITLE_WINDOW_HXX

<commit_msg>INTEGRATION: CWS changefileheader (1.4.434); FILE MERGED 2008/03/31 13:27:05 rt 1.4.434.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: AppTitleWindow.hxx,v $
 * $Revision: 1.5 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef DBAUI_TITLE_WINDOW_HXX
#define DBAUI_TITLE_WINDOW_HXX

#ifndef _SV_FIXED_HXX
#include <vcl/fixed.hxx>
#endif

namespace dbaui
{
    class OTitleWindow : public Window
    {
        FixedText   m_aSpace1;
        FixedText   m_aSpace2;
        FixedText   m_aTitle;
        Window*     m_pChild;
        BOOL        m_bShift;
        void ImplInitSettings( BOOL bFont, BOOL bForeground, BOOL bBackground );
    protected:
        virtual void DataChanged(const DataChangedEvent& rDCEvt);
    public:
        OTitleWindow(Window* _pParent,USHORT _nTitleId,WinBits _nBits,BOOL _bShift = TRUE);
        virtual ~OTitleWindow();

        // window overloads
        virtual void Resize();
        virtual void GetFocus();

        /** sets the child window which should be displayed below the title. It will be destroyed at the end.
            @param  _pChild
                The child window.
        */
        void setChildWindow(Window* _pChild);

        /** gets the child window.

            @return
                The child winodw.
        */
        inline Window* getChildWindow() const { return m_pChild; }

        /** sets the title text out of the resource
            @param  _nTitleId
                The resource id of the title text.
        */
        void setTitle(USHORT _nTitleId);

        /** Gets the min Width in Pixel which is needed to display the whole

            @return
                the min width
        */
        long GetWidthPixel() const;
    };
// .............................................................
} // namespace dbaui
// .............................................................
#endif // DBAUI_TITLE_WINDOW_HXX

<|endoftext|>


<commit_before>#include "geom.h"

int signValue(float _n) {
    if( _n > 0 ) return 1;
    else if(_n < 0) return -1;
    else return 0;
}

void wrapRad(double &_angle){
    if (_angle < -PI) _angle += PI*2.;
    if (_angle > PI) _angle -= PI*2.;
}

float mapValue(const float &value, const float &inputMin, const float &inputMax, const float &outputMin, const float &outputMax, bool clamp ) {
    if (fabs(inputMin - inputMax) < FLT_EPSILON){
        return outputMin;
    } else {
        float outVal = ((value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin);

        if( clamp ){
            if(outputMax < outputMin){
                if( outVal < outputMax )outVal = outputMax;
                else if( outVal > outputMin )outVal = outputMin;
            }else{
                if( outVal > outputMax )outVal = outputMax;
                else if( outVal < outputMin )outVal = outputMin;
            }
        }
        return outVal;
    }
}

float lerpValue(const float &_start, const float &_stop, float const &_amt) {
    if(_start!=_stop){
        return _start + (_stop-_start) * _amt;
    } else {
        return _stop;
    }
}

void scale(glm::vec3 _vec, const float _length ) {
    float l = (float)sqrt(_vec.x*_vec.x + _vec.y*_vec.y + _vec.z*_vec.z);
    if (l > 0) {
        _vec.x = (_vec.x/l)*_length;
        _vec.y = (_vec.y/l)*_length;
        _vec.z = (_vec.z/l)*_length;
    }
}

glm::vec3 getScaled(const glm::vec3 &_vec, float _length) {
    float l = (float)sqrt(_vec.x*_vec.x + _vec.y*_vec.y + _vec.z*_vec.z);
    if( l > 0 )
        return glm::vec3( (_vec.x/l)*_length, (_vec.y/l)*_length, (_vec.z/l)*_length );
    else
        return glm::vec3();
}

float getArea(const std::vector<glm::vec3> &_pts){
<<<<<<< HEAD
    float area = 0.0;
=======
    float area = 0;
>>>>>>> 799a4a58b1eac400dbb96d4d028f23b180d8e070

    for(int i=0;i<(int)_pts.size()-1;i++){
        area += _pts[i].x * _pts[i+1].y - _pts[i+1].x * _pts[i].y;
    }
    area += _pts[_pts.size()-1].x * _pts[0].y - _pts[0].x * _pts[_pts.size()-1].y;
    area *= 0.5;

    return area;
}

glm::vec3 getCentroid(const std::vector<glm::vec3> &_pts){
    glm::vec3 centroid;
    float fraq = 1.0/(float)_pts.size();
    for (int i = 0; i < _pts.size(); i++) {
        centroid += _pts[i] * fraq;
    }
    return centroid;
}

bool lexicalComparison(const glm::vec3 &_v1, const glm::vec3 &_v2) {
    if (_v1.x > _v2.x) return true;
    else if (_v1.x < _v2.x) return false;
    else if (_v1.y > _v2.y) return true;
    else return false;
}

bool isRightTurn(const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c) {
    // use the cross product to determin if we have a right turn
    return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0;
}

std::vector<glm::vec3> getConvexHull(const std::vector<glm::vec3> &_pts){
    std::vector<glm::vec3> pts;
    pts.assign(_pts.begin(),_pts.end());

    return getConvexHull(pts);
}

std::vector<glm::vec3> getConvexHull(std::vector<glm::vec3> &pts){
    std::vector<glm::vec3> hull;
    glm::vec3 h1,h2,h3;

    if (pts.size() < 3) {
        std::cout << "Error: you need at least three points to calculate the convex hull" << std::endl;
        return hull;
    }

    std::sort(pts.begin(), pts.end(), &lexicalComparison);

    hull.push_back(pts.at(0));
    hull.push_back(pts.at(1));

    int currentPoint = 2;
    int direction = 1;

    for (int i=0; i<3000; i++) { //max 1000 tries

        hull.push_back(pts.at(currentPoint));

        // look at the turn direction in the last three points
        h1 = hull.at(hull.size()-3);
        h2 = hull.at(hull.size()-2);
        h3 = hull.at(hull.size()-1);

        // while there are more than two points in the hull
        // and the last three points do not make a right turn
        while (!isRightTurn(h1, h2, h3) && hull.size() > 2) {

            // remove the middle of the last three points
            hull.erase(hull.end() - 2);

            if (hull.size() >= 3) {
                h1 = hull.at(hull.size()-3);
            }
            h2 = hull.at(hull.size()-2);
            h3 = hull.at(hull.size()-1);
        }

        // going through left-to-right calculates the top hull
        // when we get to the end, we reverse direction
        // and go back again right-to-left to calculate the bottom hull
        if (currentPoint == pts.size() -1 || currentPoint == 0) {
            direction = direction * -1;
        }

        currentPoint+=direction;

        if (hull.front()==hull.back()) {
            if(currentPoint == 3 && direction == 1){
                currentPoint = 4;
            } else {
                break;
            }
        }
    }

    return hull;
}

//This is for polygon/contour simplification - we use it to reduce the number of m_points needed in
//representing the letters as openGL shapes - will soon be moved to ofGraphics.cpp

// From: http://softsurfer.com/Archive/algorithm_0205/algorithm_0205.htm
// Copyright 2002, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.

typedef struct{
    glm::vec3 P0, P1;
} Segment;

#define norm2(v)   glm::dot(v,v)        // norm2 = squared length of vector
#define norm(v)    sqrt(norm2(v))  // norm = length of vector
#define d2(u,v)    norm2(u-v)      // distance squared = norm2 of difference
#define d(u,v)     norm(u-v)       // distance = norm of difference

//--------------------------------------------------
static void simplifyDP(float tol, glm::vec3* v, int j, int k, int* mk ){
    if (k <= j+1) // there is nothing to simplify
        return;

    // check for adequate approximation by segment S from v[j] to v[k]
    int     maxi	= j;          // index of vertex farthest from S
    float   maxd2	= 0;         // distance squared of farthest vertex
    float   tol2	= tol * tol;  // tolerance squared
    Segment S		= {v[j], v[k]};  // segment from v[j] to v[k]
    glm::vec3 u;
    u				= S.P1 - S.P0;   // segment direction vector
    float  cu		= glm::dot(u,u);     // segment length squared

    // test each vertex v[i] for max distance from S
    // compute using the Feb 2001 Algorithm's dist_ofPoint_to_Segment()
    // Note: this works in any dimension (2D, 3D, ...)
    glm::vec3  w;
    glm::vec3   Pb;                // base of perpendicular from v[i] to S
    float  b, cw, dv2;        // dv2 = distance v[i] to S squared

    for (int i=j+1; i<k; i++){
        // compute distance squared
        w = v[i] - S.P0;
        cw = glm::dot(w,u);
        if ( cw <= 0 ) dv2 = d2(v[i], S.P0);
        else if ( cu <= cw ) dv2 = d2(v[i], S.P1);
        else {
            b = (float)(cw / cu);
            Pb = S.P0 + u*b;
            dv2 = d2(v[i], Pb);
        }
        // test with current max distance squared
        if (dv2 <= maxd2) continue;

        // v[i] is a new max vertex
        maxi = i;
        maxd2 = dv2;
    }
    if (maxd2 > tol2)        // error is worse than the tolerance
    {
        // split the polyline at the farthest vertex from S
        mk[maxi] = 1;      // mark v[maxi] for the simplified polyline
        // recursively simplify the two subpolylines at v[maxi]
        simplifyDP( tol, v, j, maxi, mk );  // polyline v[j] to v[maxi]
        simplifyDP( tol, v, maxi, k, mk );  // polyline v[maxi] to v[k]
    }
    // else the approximation is OK, so ignore intermediate vertices
    return;
}

std::vector<glm::vec3> getSimplify(std::vector<glm::vec3> &_pts, float _tolerance){
    std::vector<glm::vec3> rta;
    rta.assign(_pts.begin(),_pts.end());
    simplify(rta);
    return rta;
}

void simplify(std::vector<glm::vec3> &_pts, float _tolerance){

    if(_pts.size() < 2) return;

    int n = _pts.size();

    if(n == 0) {
        return;
    }

    std::vector<glm::vec3> sV;
    sV.resize(n);

    int    i, k, m, pv;            // misc counters
    float  tol2 = _tolerance * _tolerance;       // tolerance squared
    std::vector<glm::vec3> vt;
    std::vector<int> mk;
    vt.resize(n);
    mk.resize(n,0);

    // STAGE 1.  Vertex Reduction within tolerance of prior vertex cluster
    vt[0] = _pts[0];              // start at the beginning
    for (i=k=1, pv=0; i<n; i++) {
        if (d2(_pts[i], _pts[pv]) < tol2) continue;

        vt[k++] = _pts[i];
        pv = i;
    }
    if (pv < n-1) vt[k++] = _pts[n-1];      // finish at the end

    // STAGE 2.  Douglas-Peucker polyline simplification
    mk[0] = mk[k-1] = 1;       // mark the first and last vertices
    simplifyDP( _tolerance, &vt[0], 0, k-1, &mk[0] );

    // copy marked vertices to the output simplified polyline
    for (i=m=0; i<k; i++) {
        if (mk[i]) sV[m++] = vt[i];
    }

    //get rid of the unused points
    if( m < (int)sV.size() ){
        _pts.assign( sV.begin(),sV.begin()+m );
    }else{
        _pts = sV;
    }
}
<commit_msg>fix merge<commit_after>#include "geom.h"

int signValue(float _n) {
    if( _n > 0 ) return 1;
    else if(_n < 0) return -1;
    else return 0;
}

void wrapRad(double &_angle){
    if (_angle < -PI) _angle += PI*2.;
    if (_angle > PI) _angle -= PI*2.;
}

float mapValue(const float &value, const float &inputMin, const float &inputMax, const float &outputMin, const float &outputMax, bool clamp ) {
    if (fabs(inputMin - inputMax) < FLT_EPSILON){
        return outputMin;
    } else {
        float outVal = ((value - inputMin) / (inputMax - inputMin) * (outputMax - outputMin) + outputMin);

        if( clamp ){
            if(outputMax < outputMin){
                if( outVal < outputMax )outVal = outputMax;
                else if( outVal > outputMin )outVal = outputMin;
            }else{
                if( outVal > outputMax )outVal = outputMax;
                else if( outVal < outputMin )outVal = outputMin;
            }
        }
        return outVal;
    }
}

float lerpValue(const float &_start, const float &_stop, float const &_amt) {
    if(_start!=_stop){
        return _start + (_stop-_start) * _amt;
    } else {
        return _stop;
    }
}

void scale(glm::vec3 _vec, const float _length ) {
    float l = (float)sqrt(_vec.x*_vec.x + _vec.y*_vec.y + _vec.z*_vec.z);
    if (l > 0) {
        _vec.x = (_vec.x/l)*_length;
        _vec.y = (_vec.y/l)*_length;
        _vec.z = (_vec.z/l)*_length;
    }
}

glm::vec3 getScaled(const glm::vec3 &_vec, float _length) {
    float l = (float)sqrt(_vec.x*_vec.x + _vec.y*_vec.y + _vec.z*_vec.z);
    if( l > 0 )
        return glm::vec3( (_vec.x/l)*_length, (_vec.y/l)*_length, (_vec.z/l)*_length );
    else
        return glm::vec3();
}

float getArea(const std::vector<glm::vec3> &_pts){
    float area = 0.0;

    for(int i=0;i<(int)_pts.size()-1;i++){
        area += _pts[i].x * _pts[i+1].y - _pts[i+1].x * _pts[i].y;
    }
    area += _pts[_pts.size()-1].x * _pts[0].y - _pts[0].x * _pts[_pts.size()-1].y;
    area *= 0.5;

    return area;
}

glm::vec3 getCentroid(const std::vector<glm::vec3> &_pts){
    glm::vec3 centroid;
    float fraq = 1.0/(float)_pts.size();
    for (int i = 0; i < _pts.size(); i++) {
        centroid += _pts[i] * fraq;
    }
    return centroid;
}

bool lexicalComparison(const glm::vec3 &_v1, const glm::vec3 &_v2) {
    if (_v1.x > _v2.x) return true;
    else if (_v1.x < _v2.x) return false;
    else if (_v1.y > _v2.y) return true;
    else return false;
}

bool isRightTurn(const glm::vec3 &a, const glm::vec3 &b, const glm::vec3 &c) {
    // use the cross product to determin if we have a right turn
    return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0;
}

std::vector<glm::vec3> getConvexHull(const std::vector<glm::vec3> &_pts){
    std::vector<glm::vec3> pts;
    pts.assign(_pts.begin(),_pts.end());

    return getConvexHull(pts);
}

std::vector<glm::vec3> getConvexHull(std::vector<glm::vec3> &pts){
    std::vector<glm::vec3> hull;
    glm::vec3 h1,h2,h3;

    if (pts.size() < 3) {
        std::cout << "Error: you need at least three points to calculate the convex hull" << std::endl;
        return hull;
    }

    std::sort(pts.begin(), pts.end(), &lexicalComparison);

    hull.push_back(pts.at(0));
    hull.push_back(pts.at(1));

    int currentPoint = 2;
    int direction = 1;

    for (int i=0; i<3000; i++) { //max 1000 tries

        hull.push_back(pts.at(currentPoint));

        // look at the turn direction in the last three points
        h1 = hull.at(hull.size()-3);
        h2 = hull.at(hull.size()-2);
        h3 = hull.at(hull.size()-1);

        // while there are more than two points in the hull
        // and the last three points do not make a right turn
        while (!isRightTurn(h1, h2, h3) && hull.size() > 2) {

            // remove the middle of the last three points
            hull.erase(hull.end() - 2);

            if (hull.size() >= 3) {
                h1 = hull.at(hull.size()-3);
            }
            h2 = hull.at(hull.size()-2);
            h3 = hull.at(hull.size()-1);
        }

        // going through left-to-right calculates the top hull
        // when we get to the end, we reverse direction
        // and go back again right-to-left to calculate the bottom hull
        if (currentPoint == pts.size() -1 || currentPoint == 0) {
            direction = direction * -1;
        }

        currentPoint+=direction;

        if (hull.front()==hull.back()) {
            if(currentPoint == 3 && direction == 1){
                currentPoint = 4;
            } else {
                break;
            }
        }
    }

    return hull;
}

//This is for polygon/contour simplification - we use it to reduce the number of m_points needed in
//representing the letters as openGL shapes - will soon be moved to ofGraphics.cpp

// From: http://softsurfer.com/Archive/algorithm_0205/algorithm_0205.htm
// Copyright 2002, softSurfer (www.softsurfer.com)
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.

typedef struct{
    glm::vec3 P0, P1;
} Segment;

#define norm2(v)   glm::dot(v,v)        // norm2 = squared length of vector
#define norm(v)    sqrt(norm2(v))  // norm = length of vector
#define d2(u,v)    norm2(u-v)      // distance squared = norm2 of difference
#define d(u,v)     norm(u-v)       // distance = norm of difference

//--------------------------------------------------
static void simplifyDP(float tol, glm::vec3* v, int j, int k, int* mk ){
    if (k <= j+1) // there is nothing to simplify
        return;

    // check for adequate approximation by segment S from v[j] to v[k]
    int     maxi	= j;          // index of vertex farthest from S
    float   maxd2	= 0;         // distance squared of farthest vertex
    float   tol2	= tol * tol;  // tolerance squared
    Segment S		= {v[j], v[k]};  // segment from v[j] to v[k]
    glm::vec3 u;
    u				= S.P1 - S.P0;   // segment direction vector
    float  cu		= glm::dot(u,u);     // segment length squared

    // test each vertex v[i] for max distance from S
    // compute using the Feb 2001 Algorithm's dist_ofPoint_to_Segment()
    // Note: this works in any dimension (2D, 3D, ...)
    glm::vec3  w;
    glm::vec3   Pb;                // base of perpendicular from v[i] to S
    float  b, cw, dv2;        // dv2 = distance v[i] to S squared

    for (int i=j+1; i<k; i++){
        // compute distance squared
        w = v[i] - S.P0;
        cw = glm::dot(w,u);
        if ( cw <= 0 ) dv2 = d2(v[i], S.P0);
        else if ( cu <= cw ) dv2 = d2(v[i], S.P1);
        else {
            b = (float)(cw / cu);
            Pb = S.P0 + u*b;
            dv2 = d2(v[i], Pb);
        }
        // test with current max distance squared
        if (dv2 <= maxd2) continue;

        // v[i] is a new max vertex
        maxi = i;
        maxd2 = dv2;
    }
    if (maxd2 > tol2)        // error is worse than the tolerance
    {
        // split the polyline at the farthest vertex from S
        mk[maxi] = 1;      // mark v[maxi] for the simplified polyline
        // recursively simplify the two subpolylines at v[maxi]
        simplifyDP( tol, v, j, maxi, mk );  // polyline v[j] to v[maxi]
        simplifyDP( tol, v, maxi, k, mk );  // polyline v[maxi] to v[k]
    }
    // else the approximation is OK, so ignore intermediate vertices
    return;
}

std::vector<glm::vec3> getSimplify(std::vector<glm::vec3> &_pts, float _tolerance){
    std::vector<glm::vec3> rta;
    rta.assign(_pts.begin(),_pts.end());
    simplify(rta);
    return rta;
}

void simplify(std::vector<glm::vec3> &_pts, float _tolerance){

    if(_pts.size() < 2) return;

    int n = _pts.size();

    if(n == 0) {
        return;
    }

    std::vector<glm::vec3> sV;
    sV.resize(n);

    int    i, k, m, pv;            // misc counters
    float  tol2 = _tolerance * _tolerance;       // tolerance squared
    std::vector<glm::vec3> vt;
    std::vector<int> mk;
    vt.resize(n);
    mk.resize(n,0);

    // STAGE 1.  Vertex Reduction within tolerance of prior vertex cluster
    vt[0] = _pts[0];              // start at the beginning
    for (i=k=1, pv=0; i<n; i++) {
        if (d2(_pts[i], _pts[pv]) < tol2) continue;

        vt[k++] = _pts[i];
        pv = i;
    }
    if (pv < n-1) vt[k++] = _pts[n-1];      // finish at the end

    // STAGE 2.  Douglas-Peucker polyline simplification
    mk[0] = mk[k-1] = 1;       // mark the first and last vertices
    simplifyDP( _tolerance, &vt[0], 0, k-1, &mk[0] );

    // copy marked vertices to the output simplified polyline
    for (i=m=0; i<k; i++) {
        if (mk[i]) sV[m++] = vt[i];
    }

    //get rid of the unused points
    if( m < (int)sV.size() ){
        _pts.assign( sV.begin(),sV.begin()+m );
    }else{
        _pts = sV;
    }
}
<|endoftext|>


<commit_before>#include "rapidcheck/detail/Results.h"

#include <iomanip>
#include <algorithm>

#include "rapidcheck/Show.h"

namespace rc {
namespace detail {

CaseResult::CaseResult()
    : type(CaseResult::Type::Failure) {}

CaseResult::CaseResult(Type t, std::string desc)
    : type(t)
    , description(desc) {}

bool operator==(const CaseResult &r1, const CaseResult &r2) {
  return (r1.type == r2.type) && (r1.description == r2.description);
}

bool operator!=(const CaseResult &r1, const CaseResult &r2) {
  return !(r1 == r2);
}

bool operator==(const SuccessResult &r1, const SuccessResult &r2) {
  return (r1.numSuccess == r2.numSuccess) &&
      (r1.distribution == r2.distribution);
}

bool operator!=(const SuccessResult &r1, const SuccessResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os,
                         const detail::SuccessResult &result) {
  os << "numSuccess=" << result.numSuccess << ", distribution=";
  show(result.distribution, os);
  return os;
}

bool operator==(const FailureResult &r1, const FailureResult &r2) {
  return (r1.numSuccess == r2.numSuccess) &&
      (r1.description == r2.description) && (r1.numShrinks == r2.numShrinks) &&
      (r1.counterExample == r2.counterExample);
}

bool operator!=(const FailureResult &r1, const FailureResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os,
                         const detail::FailureResult &result) {
  os << "numSuccess=" << result.numSuccess << ", description='"
     << result.description << "'"
     << ", numShrinks=" << result.numShrinks << ", counterExample=";
  show(result.counterExample, os);
  return os;
}

bool operator==(const GaveUpResult &r1, const GaveUpResult &r2) {
  return (r1.numSuccess == r2.numSuccess) && (r1.description == r2.description);
}

bool operator!=(const GaveUpResult &r1, const GaveUpResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os, const detail::GaveUpResult &result) {
  os << "numSuccess=" << result.numSuccess << ", description='"
     << result.description << "'";
  return os;
}

void printDistribution(const SuccessResult &result, std::ostream &os) {
  using Entry = std::pair<Tags, int>;
  std::vector<Entry> entries(begin(result.distribution),
                             end(result.distribution));

  std::sort(
      begin(entries),
      end(entries),
      [](const Entry &p1, const Entry &p2) { return p2.second < p1.second; });

  for (const auto &entry : entries) {
    const auto percent =
        (static_cast<double>(entry.second) / result.numSuccess) * 100.0;
    os << std::setw(5) << std::setprecision(2) << std::fixed << percent
       << "% - ";
    for (auto it = begin(entry.first); it != end(entry.first); it++) {
      if (it != begin(entry.first)) {
        os << ", ";
      }
      os << *it;
    }
    os << std::endl;
  }
  os << std::endl;
}

void printResultMessage(const SuccessResult &result, std::ostream &os) {
  os << "OK, passed " + std::to_string(result.numSuccess) + " tests";
  if (!result.distribution.empty()) {
    os << std::endl;
    printDistribution(result, os);
  }
}

void printResultMessage(const FailureResult &result, std::ostream &os) {
  os << "Falsifiable after " << (result.numSuccess + 1);
  os << " tests";
  if (result.numShrinks > 0) {
    os << " and " << result.numShrinks << " shrink";
    if (result.numShrinks > 1) {
      os << 's';
    }
  }

  os << std::endl << std::endl;

  for (const auto &item : result.counterExample) {
    os << item.first << ":" << std::endl;
    os << item.second << std::endl;
    os << std::endl;
  }

  os << result.description;
}

void printResultMessage(const GaveUpResult &result, std::ostream &os) {
  os << "Gave up after " << result.numSuccess << " tests" << std::endl;
  os << std::endl;
  os << result.description;
}

void printResultMessage(const TestResult &result, std::ostream &os) {
  SuccessResult success;
  FailureResult failure;
  GaveUpResult gaveUp;

  // TODO Make Variant cooler!
  if (result.match(success)) {
    printResultMessage(success, os);
  } else if (result.match(failure)) {
    printResultMessage(failure, os);
  } else if (result.match(gaveUp)) {
    printResultMessage(gaveUp, os);
  }
}

std::ostream &operator<<(std::ostream &os, CaseResult::Type type) {
  switch (type) {
  case CaseResult::Type::Success:
    os << "Success";
    break;

  case CaseResult::Type::Failure:
    os << "Failure";
    break;

  case CaseResult::Type::Discard:
    os << "Discard";
    break;
  }

  return os;
}

std::ostream &operator<<(std::ostream &os, const CaseResult &result) {
  os << result.type << ": " << result.description;
  return os;
}

} // namespace detail
} // namespace rc
<commit_msg>Remove extra new line in distribution printing<commit_after>#include "rapidcheck/detail/Results.h"

#include <iomanip>
#include <algorithm>

#include "rapidcheck/Show.h"

namespace rc {
namespace detail {

CaseResult::CaseResult()
    : type(CaseResult::Type::Failure) {}

CaseResult::CaseResult(Type t, std::string desc)
    : type(t)
    , description(desc) {}

bool operator==(const CaseResult &r1, const CaseResult &r2) {
  return (r1.type == r2.type) && (r1.description == r2.description);
}

bool operator!=(const CaseResult &r1, const CaseResult &r2) {
  return !(r1 == r2);
}

bool operator==(const SuccessResult &r1, const SuccessResult &r2) {
  return (r1.numSuccess == r2.numSuccess) &&
      (r1.distribution == r2.distribution);
}

bool operator!=(const SuccessResult &r1, const SuccessResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os,
                         const detail::SuccessResult &result) {
  os << "numSuccess=" << result.numSuccess << ", distribution=";
  show(result.distribution, os);
  return os;
}

bool operator==(const FailureResult &r1, const FailureResult &r2) {
  return (r1.numSuccess == r2.numSuccess) &&
      (r1.description == r2.description) && (r1.numShrinks == r2.numShrinks) &&
      (r1.counterExample == r2.counterExample);
}

bool operator!=(const FailureResult &r1, const FailureResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os,
                         const detail::FailureResult &result) {
  os << "numSuccess=" << result.numSuccess << ", description='"
     << result.description << "'"
     << ", numShrinks=" << result.numShrinks << ", counterExample=";
  show(result.counterExample, os);
  return os;
}

bool operator==(const GaveUpResult &r1, const GaveUpResult &r2) {
  return (r1.numSuccess == r2.numSuccess) && (r1.description == r2.description);
}

bool operator!=(const GaveUpResult &r1, const GaveUpResult &r2) {
  return !(r1 == r2);
}

std::ostream &operator<<(std::ostream &os, const detail::GaveUpResult &result) {
  os << "numSuccess=" << result.numSuccess << ", description='"
     << result.description << "'";
  return os;
}

void printDistribution(const SuccessResult &result, std::ostream &os) {
  using Entry = std::pair<Tags, int>;
  std::vector<Entry> entries(begin(result.distribution),
                             end(result.distribution));

  std::sort(
      begin(entries),
      end(entries),
      [](const Entry &p1, const Entry &p2) { return p2.second < p1.second; });

  for (const auto &entry : entries) {
    const auto percent =
        (static_cast<double>(entry.second) / result.numSuccess) * 100.0;
    os << std::setw(5) << std::setprecision(2) << std::fixed << percent
       << "% - ";
    for (auto it = begin(entry.first); it != end(entry.first); it++) {
      if (it != begin(entry.first)) {
        os << ", ";
      }
      os << *it;
    }
    os << std::endl;
  }
}

void printResultMessage(const SuccessResult &result, std::ostream &os) {
  os << "OK, passed " + std::to_string(result.numSuccess) + " tests";
  if (!result.distribution.empty()) {
    os << std::endl;
    printDistribution(result, os);
  }
}

void printResultMessage(const FailureResult &result, std::ostream &os) {
  os << "Falsifiable after " << (result.numSuccess + 1);
  os << " tests";
  if (result.numShrinks > 0) {
    os << " and " << result.numShrinks << " shrink";
    if (result.numShrinks > 1) {
      os << 's';
    }
  }

  os << std::endl << std::endl;

  for (const auto &item : result.counterExample) {
    os << item.first << ":" << std::endl;
    os << item.second << std::endl;
    os << std::endl;
  }

  os << result.description;
}

void printResultMessage(const GaveUpResult &result, std::ostream &os) {
  os << "Gave up after " << result.numSuccess << " tests" << std::endl;
  os << std::endl;
  os << result.description;
}

void printResultMessage(const TestResult &result, std::ostream &os) {
  SuccessResult success;
  FailureResult failure;
  GaveUpResult gaveUp;

  // TODO Make Variant cooler!
  if (result.match(success)) {
    printResultMessage(success, os);
  } else if (result.match(failure)) {
    printResultMessage(failure, os);
  } else if (result.match(gaveUp)) {
    printResultMessage(gaveUp, os);
  }
}

std::ostream &operator<<(std::ostream &os, CaseResult::Type type) {
  switch (type) {
  case CaseResult::Type::Success:
    os << "Success";
    break;

  case CaseResult::Type::Failure:
    os << "Failure";
    break;

  case CaseResult::Type::Discard:
    os << "Discard";
    break;
  }

  return os;
}

std::ostream &operator<<(std::ostream &os, const CaseResult &result) {
  os << result.type << ": " << result.description;
  return os;
}

} // namespace detail
} // namespace rc
<|endoftext|>


<commit_before>#include <src/servers/Server_Common/Exd/ExdData.h>

#include "CalcBattle.h"
#include "Actor.h"
#include "Player.h"
#include <cmath>

using namespace Core::Entity;

extern Core::Data::ExdData g_exdData;

/*
   Class used for battle-related formulas and calculations.
   Big thanks to the Theoryjerks group!

   NOTE:
   Formulas here shouldn't be considered final. It's possible that the formula it was based on is correct but
   wasn't implemented correctly here, or approximated things due to limited knowledge of how things work in retail.
   It's also possible that we're using formulas that were correct for previous patches, but not the current version.

   TODO:

   Base HP val modifier. I can only find values for levels 50~70.
   Attack power (and healing power). Needs more research on this.
   Damage outgoing calculations. This includes auto-attacks, etc.

*/

// Don't know too much about this formula, but seems to work for some of the levels tested.
// Originally from Player.cpp, calculateStats().

uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer )
{
   float base = 0.0f;
   uint8_t level = pPlayer->getLevel();

   if (level < 51)
      base = 0.053f * ( level * level ) + ( 1.022f * level ) - 0.907f + 20;
   else
      base = 1.627f * level + 120.773f;

   return base;
}

// Leggerless' HP Formula
// ROUNDDOWN(JobModHP * (BaseHP / 100)) + ROUNDDOWN(VitHPMod / 100 * (VIT - BaseDET))

uint32_t CalcBattle::calculateMaxHp( PlayerPtr pPlayer )
{
   // TODO: Replace ApproxBaseHP with something that can get us an accurate BaseHP.
   // Is there any way to pull BaseHP without having to manually use a pet for every level, and using the values from a table?
   // More info here: https://docs.google.com/spreadsheets/d/1de06KGT0cNRUvyiXNmjNgcNvzBCCQku7jte5QxEQRbs/edit?usp=sharing

   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() )
      return 0;

   uint8_t level = pPlayer->getLevel();

   float baseStat = calculateBaseStat( pPlayer );
   uint16_t vitStat = pPlayer->getStats().vit;
   uint16_t hpMod = paramGrowthInfoIt->second.hp_mod;
   uint16_t jobModHp = classInfoIt->second.mod_hp;
   float approxBaseHp = 0.0f; // Read above

   // These values are not precise.

   if ( level >= 60 )
      approxBaseHp = 2600 + ( level - 60 ) * 100;
   else if ( level >= 50 )
      approxBaseHp = 1700 + ( ( level - 50 ) * ( 1700 * 1.04325f ) );
   else
      approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.7596f;

   uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hpMod / 100.0f * ( vitStat - baseStat ) );

   return result;
}

// Leggerless' MP Formula
// ROUNDDOWN(((ROUNDDOWN(((PIE - BaseDET) * PieMPMod/100),0) + BaseMP) * JobModMP / 100),0)

uint32_t CalcBattle::calculateMaxMp( PlayerPtr pPlayer )
{
   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() )
      return 0;

   float baseStat = calculateBaseStat( pPlayer );
   uint16_t piety = pPlayer->getStats().pie;
   uint16_t pietyScalar = paramGrowthInfoIt->second.mp_mod;
   uint16_t jobModMp = classInfoIt->second.mod_mpcpgp;
   uint16_t baseMp = paramGrowthInfoIt->second.mp_const;

   uint16_t result = floor( floor( piety - baseStat ) * ( pietyScalar / 100 ) + baseMp ) * jobModMp / 100;

   return result;
}

uint32_t CalcBattle::calculateHealValue( PlayerPtr pPlayer, uint32_t potency )
{
   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end())
      return 0;

   auto jobModVal = classInfoIt->second;

   // consider 3% variation
   return potency / 10;
}<commit_msg>New BaseStat formulas (SB, HW, ARR)<commit_after>#include <src/servers/Server_Common/Exd/ExdData.h>

#include "CalcBattle.h"
#include "Actor.h"
#include "Player.h"
#include <cmath>

using namespace Core::Entity;

extern Core::Data::ExdData g_exdData;

/*
   Class used for battle-related formulas and calculations.
   Big thanks to the Theoryjerks group!

   NOTE:
   Formulas here shouldn't be considered final. It's possible that the formula it was based on is correct but
   wasn't implemented correctly here, or approximated things due to limited knowledge of how things work in retail.
   It's also possible that we're using formulas that were correct for previous patches, but not the current version.

   TODO:

   Base HP val modifier. I can only find values for levels 50~70.
   Attack power (and healing power). Needs more research on this.
   Damage outgoing calculations. This includes auto-attacks, etc.

*/

// 3 Versions. SB and HW are linear, ARR is polynomial.
// Originally from Player.cpp, calculateStats().

uint32_t CalcBattle::calculateBaseStat( PlayerPtr pPlayer )
{
   float base = 0.0f;
   uint8_t level = pPlayer->getLevel();

   // SB Base Stat Formula  (Aligned)
   if ( level > 60 )
   {
      base = ( ( ( level == 61) ? 224 : 220 ) + ( level - 61 ) * 8);
   }
   // HW Base Stat Formula  (Aligned)
   else if ( level > 50 )
      base = 1.63f * level + 121.02f;
   // ARR Base Stat Formula (Off by one in several cases)
   else
      // Old: base = 0.053f * ( level * level ) + ( 1.022f * level ) - 0.907f + 20;
      // V1: base = 0.0523f * ( level * level ) + ( 1.04f * level ) + 19.405;
      // V2: base = 0.05223f * ( level * level ) + ( 1.0405f * level ) + 19.405;
      base = 0.052602 * ( level * level ) + ( 1.0179f * level ) + 19.6;

   return base;
}

// Leggerless' HP Formula
// ROUNDDOWN(JobModHP * (BaseHP / 100)) + ROUNDDOWN(VitHPMod / 100 * (VIT - BaseDET))

uint32_t CalcBattle::calculateMaxHp( PlayerPtr pPlayer )
{
   // TODO: Replace ApproxBaseHP with something that can get us an accurate BaseHP.
   // Is there any way to pull BaseHP without having to manually use a pet for every level, and using the values from a table?
   // More info here: https://docs.google.com/spreadsheets/d/1de06KGT0cNRUvyiXNmjNgcNvzBCCQku7jte5QxEQRbs/edit?usp=sharing

   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() )
      return 0;

   uint8_t level = pPlayer->getLevel();

   float baseStat = calculateBaseStat( pPlayer );
   uint16_t vitStat = pPlayer->getStats().vit;
   uint16_t hpMod = paramGrowthInfoIt->second.hp_mod;
   uint16_t jobModHp = classInfoIt->second.mod_hp;
   float approxBaseHp = 0.0f; // Read above

   // These values are not precise.

   if ( level >= 60 )
      approxBaseHp = 2600 + ( level - 60 ) * 100;
   else if ( level >= 50 )
      approxBaseHp = 1700 + ( ( level - 50 ) * ( 1700 * 1.04325f ) );
   else
      approxBaseHp = paramGrowthInfoIt->second.mp_const * 0.7596f;

   uint16_t result = floor( jobModHp * ( approxBaseHp / 100.0f ) ) + floor( hpMod / 100.0f * ( vitStat - baseStat ) );

   return result;
}

// Leggerless' MP Formula
// ROUNDDOWN(((ROUNDDOWN(((PIE - BaseDET) * PieMPMod/100),0) + BaseMP) * JobModMP / 100),0)

uint32_t CalcBattle::calculateMaxMp( PlayerPtr pPlayer )
{
   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end() )
      return 0;

   float baseStat = calculateBaseStat( pPlayer );
   uint16_t piety = pPlayer->getStats().pie;
   uint16_t pietyScalar = paramGrowthInfoIt->second.mp_mod;
   uint16_t jobModMp = classInfoIt->second.mod_mpcpgp;
   uint16_t baseMp = paramGrowthInfoIt->second.mp_const;

   uint16_t result = floor( floor( piety - baseStat ) * ( pietyScalar / 100 ) + baseMp ) * jobModMp / 100;

   return result;
}

uint32_t CalcBattle::calculateHealValue( PlayerPtr pPlayer, uint32_t potency )
{
   auto classInfoIt = g_exdData.m_classJobInfoMap.find( pPlayer->getClass() );
   auto paramGrowthInfoIt = g_exdData.m_paramGrowthInfoMap.find( pPlayer->getLevel() );

   if ( classInfoIt == g_exdData.m_classJobInfoMap.end() ||
      paramGrowthInfoIt == g_exdData.m_paramGrowthInfoMap.end())
      return 0;

   auto jobModVal = classInfoIt->second;

   // consider 3% variation
   return potency / 10;
}<|endoftext|>


<commit_before>// @(#)root/io:$Id$
// Author: Philippe Canal, Witold Pokorski, and Guilherme Amadio

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TBufferMerger
#define ROOT_TBufferMerger

#include "TMemFile.h"

#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>

class TBufferFile;
class TFile;

namespace ROOT {
namespace Experimental {

class TBufferMergerFile;

/**
 * \class TBufferMerger TBufferMerger.hxx
 * \ingroup IO
 *
 * TBufferMerger is a class to facilitate writing data in
 * parallel from multiple threads, while writing to a single
 * output file. Its purpose is similar to TParallelMergingFile,
 * but instead of using processes that connect to a network
 * socket, TBufferMerger uses threads that each write to a
 * TBufferMergerFile, which in turn push data into a queue
 * managed by the TBufferMerger.
 */

class TBufferMerger {
public:
   /** Constructor
    * @param name Output file name
    * @param option Output file creation options
    * @param compression Output file compression level
    */
   TBufferMerger(const char *name, Option_t *option = "RECREATE", Int_t compress = 1);

   /** Constructor
    * @param output Output \c TFile
    */
   TBufferMerger(std::unique_ptr<TFile> output);

   /** Destructor */
   virtual ~TBufferMerger();

   /** Returns a TBufferMergerFile to which data can be written.
    *  At the end, all TBufferMergerFiles get merged into the output file.
    *  The user is responsible to "cd" into the file to associate objects
    *  such as histograms or trees to it.
    *
    *  After the creation of this file, the user must reset the kMustCleanup
    *  bit on any objects attached to it and take care of their deletion, as
    *  there is a possibility that a race condition will happen that causes
    *  a crash if ROOT manages these objects.
    */
   std::shared_ptr<TBufferMergerFile> GetFile();

   /** Returns the number of buffers currently in the queue. */
   size_t GetQueueSize() const;

   /** Register a user callback function to be called after a buffer has been
    *  removed from the merging queue and finished being processed. This
    *  function can be useful to allow asynchronous launching of new tasks to
    *  push more data into the queue once its size satisfies user requirements.
    */
   void RegisterCallback(const std::function<void(void)> &f);

   /** Returns the current value of the auto save setting in bytes (default = 0). */
   size_t GetAutoSave() const;

   /** By default, TBufferMerger will call TFileMerger::PartialMerge() for each
    *  buffer pushed onto its merge queue. This function lets the user change
    *  this behaviour by telling TBufferMerger to accumulate at least @param size
    *  bytes in memory before performing a partial merge and flushing to disk.
    *  This can be useful to avoid an excessive amount of work to happen in the
    *  output thread, as the number of TTree headers (which require compression)
    *  written to disk can be reduced.
    */
   void SetAutoSave(size_t size);

   friend class TBufferMergerFile;

private:
   /** TBufferMerger has no default constructor */
   TBufferMerger();

   /** TBufferMerger has no copy constructor */
   TBufferMerger(const TBufferMerger &);

   /** TBufferMerger has no copy operator */
   TBufferMerger &operator=(const TBufferMerger &);

   void Init(std::unique_ptr<TFile>);

   void Push(TBufferFile *buffer);
   void WriteOutputFile();

   TFile* fFile;                                                 //< Output file.
   size_t fAutoSave;                                             //< AutoSave only every fAutoSave bytes
   std::mutex fQueueMutex;                                       //< Mutex used to lock fQueue
   std::condition_variable fDataAvailable;                       //< Condition variable used to wait for data
   std::queue<TBufferFile *> fQueue;                             //< Queue to which data is pushed and merged
   std::unique_ptr<std::thread> fMergingThread;                  //< Worker thread that writes to disk
   std::vector<std::weak_ptr<TBufferMergerFile>> fAttachedFiles; //< Attached files
   std::function<void(void)> fCallback;                          //< Callback for when data is removed from queue

   ClassDef(TBufferMerger, 1);
};

/**
 * \class TBufferMerger TBufferMerger.hxx
 * \ingroup IO
 *
 * A TBufferMergerFile is similar to a TMemFile, but when data
 * is written to it, it is appended to the TBufferMerger queue.
 * The TBufferMerger merges all data into the output file on disk.
 */

class TBufferMergerFile : public TMemFile {
private:
   TBufferMerger &fMerger; //< TBufferMerger this file is attached to

   /** Constructor. Can only be called by TBufferMerger.
    * @param m Merger this file is attached to. */
   TBufferMergerFile(TBufferMerger &m);

   /** TBufferMergerFile has no default constructor. */
   TBufferMergerFile();

   /** TBufferMergerFile has no copy constructor. */
   TBufferMergerFile(const TBufferMergerFile &);

   /** TBufferMergerFile has no copy operator */
   TBufferMergerFile &operator=(const TBufferMergerFile &);

   friend class TBufferMerger;

public:
   /** Destructor */
   ~TBufferMergerFile();

   using TMemFile::Write;

   /** Write data into a TBufferFile and append it to TBufferMerger.
    * @param name Name
    * @param opt  Options
    * @param bufsize Buffer size
    * This function must be called before the TBufferMergerFile gets destroyed,
    * or no data is appended to the TBufferMerger.
    */
   virtual Int_t Write(const char *name = nullptr, Int_t opt = 0, Int_t bufsize = 0) override;

   ClassDefOverride(TBufferMergerFile, 0);
};

} // namespace Experimental
} // namespace ROOT

#endif
<commit_msg>Revert the ClassDef version back to 0.<commit_after>// @(#)root/io:$Id$
// Author: Philippe Canal, Witold Pokorski, and Guilherme Amadio

/*************************************************************************
 * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TBufferMerger
#define ROOT_TBufferMerger

#include "TMemFile.h"

#include <condition_variable>
#include <functional>
#include <memory>
#include <mutex>
#include <queue>
#include <thread>

class TBufferFile;
class TFile;

namespace ROOT {
namespace Experimental {

class TBufferMergerFile;

/**
 * \class TBufferMerger TBufferMerger.hxx
 * \ingroup IO
 *
 * TBufferMerger is a class to facilitate writing data in
 * parallel from multiple threads, while writing to a single
 * output file. Its purpose is similar to TParallelMergingFile,
 * but instead of using processes that connect to a network
 * socket, TBufferMerger uses threads that each write to a
 * TBufferMergerFile, which in turn push data into a queue
 * managed by the TBufferMerger.
 */

class TBufferMerger {
public:
   /** Constructor
    * @param name Output file name
    * @param option Output file creation options
    * @param compression Output file compression level
    */
   TBufferMerger(const char *name, Option_t *option = "RECREATE", Int_t compress = 1);

   /** Constructor
    * @param output Output \c TFile
    */
   TBufferMerger(std::unique_ptr<TFile> output);

   /** Destructor */
   virtual ~TBufferMerger();

   /** Returns a TBufferMergerFile to which data can be written.
    *  At the end, all TBufferMergerFiles get merged into the output file.
    *  The user is responsible to "cd" into the file to associate objects
    *  such as histograms or trees to it.
    *
    *  After the creation of this file, the user must reset the kMustCleanup
    *  bit on any objects attached to it and take care of their deletion, as
    *  there is a possibility that a race condition will happen that causes
    *  a crash if ROOT manages these objects.
    */
   std::shared_ptr<TBufferMergerFile> GetFile();

   /** Returns the number of buffers currently in the queue. */
   size_t GetQueueSize() const;

   /** Register a user callback function to be called after a buffer has been
    *  removed from the merging queue and finished being processed. This
    *  function can be useful to allow asynchronous launching of new tasks to
    *  push more data into the queue once its size satisfies user requirements.
    */
   void RegisterCallback(const std::function<void(void)> &f);

   /** Returns the current value of the auto save setting in bytes (default = 0). */
   size_t GetAutoSave() const;

   /** By default, TBufferMerger will call TFileMerger::PartialMerge() for each
    *  buffer pushed onto its merge queue. This function lets the user change
    *  this behaviour by telling TBufferMerger to accumulate at least @param size
    *  bytes in memory before performing a partial merge and flushing to disk.
    *  This can be useful to avoid an excessive amount of work to happen in the
    *  output thread, as the number of TTree headers (which require compression)
    *  written to disk can be reduced.
    */
   void SetAutoSave(size_t size);

   friend class TBufferMergerFile;

private:
   /** TBufferMerger has no default constructor */
   TBufferMerger();

   /** TBufferMerger has no copy constructor */
   TBufferMerger(const TBufferMerger &);

   /** TBufferMerger has no copy operator */
   TBufferMerger &operator=(const TBufferMerger &);

   void Init(std::unique_ptr<TFile>);

   void Push(TBufferFile *buffer);
   void WriteOutputFile();

   TFile* fFile;                                                 //< Output file.
   size_t fAutoSave;                                             //< AutoSave only every fAutoSave bytes
   std::mutex fQueueMutex;                                       //< Mutex used to lock fQueue
   std::condition_variable fDataAvailable;                       //< Condition variable used to wait for data
   std::queue<TBufferFile *> fQueue;                             //< Queue to which data is pushed and merged
   std::unique_ptr<std::thread> fMergingThread;                  //< Worker thread that writes to disk
   std::vector<std::weak_ptr<TBufferMergerFile>> fAttachedFiles; //< Attached files
   std::function<void(void)> fCallback;                          //< Callback for when data is removed from queue

   ClassDef(TBufferMerger, 0);
};

/**
 * \class TBufferMerger TBufferMerger.hxx
 * \ingroup IO
 *
 * A TBufferMergerFile is similar to a TMemFile, but when data
 * is written to it, it is appended to the TBufferMerger queue.
 * The TBufferMerger merges all data into the output file on disk.
 */

class TBufferMergerFile : public TMemFile {
private:
   TBufferMerger &fMerger; //< TBufferMerger this file is attached to

   /** Constructor. Can only be called by TBufferMerger.
    * @param m Merger this file is attached to. */
   TBufferMergerFile(TBufferMerger &m);

   /** TBufferMergerFile has no default constructor. */
   TBufferMergerFile();

   /** TBufferMergerFile has no copy constructor. */
   TBufferMergerFile(const TBufferMergerFile &);

   /** TBufferMergerFile has no copy operator */
   TBufferMergerFile &operator=(const TBufferMergerFile &);

   friend class TBufferMerger;

public:
   /** Destructor */
   ~TBufferMergerFile();

   using TMemFile::Write;

   /** Write data into a TBufferFile and append it to TBufferMerger.
    * @param name Name
    * @param opt  Options
    * @param bufsize Buffer size
    * This function must be called before the TBufferMergerFile gets destroyed,
    * or no data is appended to the TBufferMerger.
    */
   virtual Int_t Write(const char *name = nullptr, Int_t opt = 0, Int_t bufsize = 0) override;

   ClassDefOverride(TBufferMergerFile, 0);
};

} // namespace Experimental
} // namespace ROOT

#endif
<|endoftext|>