//--------------------------------------------------------------------------- // Greenplum Database // Copyright (C) 2011 EMC Corp. // // @filename: // CJobFactory.h // // @doc: // Highly concurrent job factory; // Uses bulk memory allocation and atomic primitives to // create and recycle jobs with minimal sychronization; //--------------------------------------------------------------------------- #ifndef GPOPT_CJobFactory_H #define GPOPT_CJobFactory_H #include "gpos/base.h" #include "gpos/common/CSyncPool.h" #include "gpopt/search/CJob.h" #include "gpopt/search/CJobGroupExploration.h" #include "gpopt/search/CJobGroupExpressionExploration.h" #include "gpopt/search/CJobGroupExpressionImplementation.h" #include "gpopt/search/CJobGroupExpressionOptimization.h" #include "gpopt/search/CJobGroupImplementation.h" #include "gpopt/search/CJobGroupOptimization.h" #include "gpopt/search/CJobTest.h" #include "gpopt/search/CJobTransformation.h" namespace gpopt { using namespace gpos; //--------------------------------------------------------------------------- // @class: // CJobFactory // // @doc: // Highly concurrent job factory // // The factory uses bulk memory allocation to create and recycle jobs with // minimal synchronization. The factory maintains a lock-free list defined // by the class CSyncPool for each job type. This allows concurrent // retrieval of jobs from the lists without the need for synchronization // through heavy locking operations. // A lock-free list is pre-allocated as an array of given size. The // allocation of lock-free lists happens lazily when the first job of a // given type is created. // Each job is given a unique id. When a job needs to be retrieved from // the list, atomic operations are used to reserve a free job object and // return it to the caller. // //--------------------------------------------------------------------------- class CJobFactory { private: // memory pool CMemoryPool *m_mp; // number of jobs in each pool const ULONG m_ulJobs; // container for testing jobs CSyncPool *m_pspjTest; // container for group optimization jobs CSyncPool *m_pspjGroupOptimization; // container for group implementation jobs CSyncPool *m_pspjGroupImplementation; // container for group exploration jobs CSyncPool *m_pspjGroupExploration; // container for group expression optimization jobs CSyncPool *m_pspjGroupExpressionOptimization; // container for group expression implementation jobs CSyncPool *m_pspjGroupExpressionImplementation; // container for group expression exploration jobs CSyncPool *m_pspjGroupExpressionExploration; // container for transformation jobs CSyncPool *m_pspjTransformation; // retrieve job of specific type template T * PtRetrieve(CSyncPool *&pspt) { if (nullptr == pspt) { pspt = GPOS_NEW(m_mp) CSyncPool(m_mp, m_ulJobs); pspt->Init(GPOS_OFFSET(T, m_id)); } return pspt->PtRetrieve(); } // release job template void Release(T *pt, CSyncPool *pspt) { GPOS_ASSERT(nullptr != pt); GPOS_ASSERT(nullptr != pspt); pspt->Recycle(pt); } // truncate job pool template void TruncatePool(CSyncPool *&pspt) { GPOS_DELETE(pspt); pspt = nullptr; } public: CJobFactory(const CJobFactory &) = delete; // ctor CJobFactory(CMemoryPool *mp, ULONG ulJobs); // dtor ~CJobFactory(); // create job of specific type CJob *PjCreate(CJob::EJobType ejt); // release completed job void Release(CJob *pj); // truncate the container for the specific job type void Truncate(CJob::EJobType ejt); }; // class CJobFactory } // namespace gpopt #endif // !GPOPT_CJobFactory_H // EOF