cling/lib/Interpreter/TransactionPool.h

105 lines
3.0 KiB
C++

//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
#ifndef CLING_TRANSACTION_POOL_H
#define CLING_TRANSACTION_POOL_H
#include "cling/Interpreter/Transaction.h"
#include "llvm/ADT/SmallVector.h"
namespace clang {
class Sema;
}
namespace cling {
class TransactionPool {
#define TRANSACTIONS_IN_BLOCK 8
#define POOL_SIZE 2 * TRANSACTIONS_IN_BLOCK
private:
// It is twice the size of the block because there might be easily around 8
// transactions in flight which can be empty, which might lead to refill of
// the smallvector and then the return for reuse will exceed the capacity
// of the smallvector causing redundant copy of the elements.
//
llvm::SmallVector<Transaction*, POOL_SIZE> m_Transactions;
///\brief The Sema required by cling::Transactions' ctor.
///
clang::Sema& m_Sema;
// We need to free them in blocks.
//
//llvm::SmallVector<Transaction*, 64> m_TransactionBlocks;
#ifndef NDEBUG
bool m_Debug;
#endif
private:
void RefillPool() {
// Allocate them in one block, containing 8 transactions.
//Transaction* arrayStart = new Transaction[TRANSACTIONS_IN_BLOCK]();
for (size_t i = 0; i < TRANSACTIONS_IN_BLOCK; ++i)
m_Transactions.push_back(new Transaction(m_Sema));
//m_TransactionBlocks.push_back(arrayStart);
}
public:
TransactionPool(clang::Sema& S) : m_Sema(S) {
#ifndef NDEBUG
m_Debug = false;
#endif
RefillPool();
}
~TransactionPool() {
for (size_t i = 0, e = m_Transactions.size(); i < e; ++i)
delete m_Transactions[i];
}
Transaction* takeTransaction() {
if (m_Transactions.size() == 0)
RefillPool();
Transaction* T = m_Transactions.pop_back_val();
#ifndef NDEBUG
// *Very useful for debugging purposes and setting breakpoints in gdb.
if (m_Debug)
T = new Transaction(m_Sema);
#endif
T->m_State = Transaction::kCollecting;
return T;
}
void releaseTransaction(Transaction* T) {
assert((T->getState() == Transaction::kCompleted ||
T->getState() == Transaction::kRolledBack)
&& "Transaction must completed!");
if (m_Transactions.size() == POOL_SIZE) {
// Tell the parent that T is gone.
if (T->getParent())
T->getParent()->removeNestedTransaction(T);
// don't overflow the pool
delete T;
return;
}
T->reset();
T->m_State = Transaction::kNumStates;
m_Transactions.push_back(T);
}
#undef POOL_SIZE
#undef TRANSACTIONS_IN_BLOCK
};
} // end namespace cling
#endif // CLING_TRANSACTION_POOL_H