2013-08-01 14:27:40 +04:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vvasilev@cern.ch>
2014-01-07 14:08:37 +04:00
//
// 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.
2013-08-01 14:27:40 +04:00
//------------------------------------------------------------------------------
# ifndef CLING_TRANSACTION_POOL_H
# define CLING_TRANSACTION_POOL_H
# include "cling/Interpreter/Transaction.h"
# include "llvm/ADT/SmallVector.h"
2013-08-04 20:31:52 +04:00
namespace clang {
2014-03-28 17:53:34 +04:00
class Sema ;
2013-08-04 20:31:52 +04:00
}
2013-08-01 14:27:40 +04:00
namespace cling {
class TransactionPool {
2016-09-10 18:54:46 +03:00
enum {
2016-09-12 12:08:07 +03:00
# ifdef NDEBUG
kDebugMode = 0 ,
# else
kDebugMode = 1 , // Always use a new Transaction
# endif
2021-03-31 12:18:19 +03:00
kPoolSize = 16
2016-09-10 18:54:46 +03:00
} ;
2013-08-01 14:27:40 +04:00
// 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.
//
2016-09-10 18:54:46 +03:00
llvm : : SmallVector < Transaction * , kPoolSize > m_Transactions ;
2013-08-01 14:27:40 +04:00
public :
2016-06-27 02:43:40 +03:00
TransactionPool ( ) { }
2013-08-01 14:27:40 +04:00
~ TransactionPool ( ) {
2016-06-27 02:43:40 +03:00
// Only free the memory as anything put in m_Transactions will have
// already been destructed in releaseTransaction
for ( Transaction * T : m_Transactions )
: : operator delete ( T ) ;
2013-08-01 14:27:40 +04:00
}
2016-06-27 02:43:40 +03:00
Transaction * takeTransaction ( clang : : Sema & S ) {
Transaction * T ;
2021-03-30 17:58:29 +03:00
if ( kDebugMode | | m_Transactions . empty ( ) )
T = new Transaction ( S ) ;
else
2016-06-27 02:43:40 +03:00
T = new ( m_Transactions . pop_back_val ( ) ) Transaction ( S ) ;
2014-04-15 19:26:44 +04:00
2013-08-04 20:38:42 +04:00
return T ;
2013-08-01 14:27:40 +04:00
}
2016-09-12 22:39:38 +03:00
// Transaction T must be from call to TransactionPool::takeTransaction
//
2016-06-27 02:43:40 +03:00
void releaseTransaction ( Transaction * T , bool reuse = true ) {
2021-03-31 16:10:21 +03:00
assert ( ( m_Transactions . empty ( ) | | m_Transactions . back ( ) ! = T ) \
& & " Transaction already in pool " ) ;
2016-06-27 02:43:40 +03:00
if ( reuse ) {
assert ( ( T - > getState ( ) = = Transaction : : kCompleted | |
T - > getState ( ) = = Transaction : : kRolledBack )
2021-03-30 17:58:29 +03:00
& & " Transaction must be completed! " ) ;
2016-09-12 12:08:07 +03:00
// Force reuse to off when not in Debug mode
if ( kDebugMode )
reuse = false ;
2016-06-27 02:43:40 +03:00
}
2014-04-14 18:53:39 +04:00
2015-06-08 15:50:58 +03:00
// Tell the parent that T is gone.
if ( T - > getParent ( ) )
T - > getParent ( ) - > removeNestedTransaction ( T ) ;
2014-04-14 18:53:39 +04:00
2016-06-27 02:43:40 +03:00
// don't overflow the pool
2016-09-10 18:54:46 +03:00
if ( reuse & & ( m_Transactions . size ( ) < kPoolSize ) ) {
2016-06-27 02:43:40 +03:00
T - > m_State = Transaction : : kNumStates ;
2021-03-30 17:58:29 +03:00
T - > ~ Transaction ( ) ;
2016-06-27 02:43:40 +03:00
m_Transactions . push_back ( T ) ;
}
else
2021-03-30 17:58:29 +03:00
delete T ;
2013-08-01 14:27:40 +04:00
}
} ;
} // end namespace cling
# endif // CLING_TRANSACTION_POOL_H