prefetch_impl.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:8k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: prefetch_impl.cpp,v $
  4.  * PRODUCTION Revision 1000.2  2004/06/01 19:23:32  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: prefetch_impl.cpp,v 1000.2 2004/06/01 19:23:32 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the author in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author: Aleksey Grichenko, Eugene Vasilchenko
  35. *
  36. * File Description:
  37. *   Prefetch implementation
  38. *
  39. */
  40. #include <ncbi_pch.hpp>
  41. #include <objmgr/impl/prefetch_impl.hpp>
  42. #include <corelib/ncbimtx.hpp>
  43. #include <objmgr/bioseq_handle.hpp>
  44. #include <objmgr/scope.hpp>
  45. #include <objmgr/impl/tse_info.hpp>
  46. #include <objmgr/impl/scope_impl.hpp>
  47. #include <objmgr/impl/data_source.hpp>
  48. #include <objmgr/seqmatch_info.hpp>
  49. BEGIN_NCBI_SCOPE
  50. BEGIN_SCOPE(objects)
  51. // NOTE: Max. value for semaphore must be prefetch depth + 1, because
  52. // one extra-Post will be called when the token impl. is released.
  53. CPrefetchToken_Impl::CPrefetchToken_Impl(const TIds& ids, unsigned int depth)
  54.     : m_TokenCount(0),
  55.       m_TSESemaphore(depth, max(depth+1, depth)),
  56.       m_Non_locking(false)
  57. {
  58.     m_Ids = ids;
  59. }
  60. CPrefetchToken_Impl::~CPrefetchToken_Impl(void)
  61. {
  62.     return;
  63. }
  64. void CPrefetchToken_Impl::x_InitPrefetch(CScope& scope)
  65. {
  66.     m_TSEs.resize(m_Ids.size());
  67.     m_CurrentId = 0;
  68.     CRef<CDataSource> source(scope.GetImpl().GetFirstLoaderSource());
  69.     if (!source) {
  70.         return;
  71.     }
  72.     source->Prefetch(*this);
  73. }
  74. void CPrefetchToken_Impl::x_SetNon_locking(void)
  75. {
  76.     m_Non_locking = true;
  77. }
  78. void CPrefetchToken_Impl::AddResolvedId(size_t id_idx, TTSE_Lock tse)
  79. {
  80.     CFastMutexGuard guard(m_Lock);
  81.     if ( m_Non_locking ) {
  82.         m_TSESemaphore.Post();
  83.         return;
  84.     }
  85.     if (m_Ids.empty()  ||  id_idx < m_CurrentId) {
  86.         // Token has been cleaned or id already passed, do not lock the TSE
  87.         return;
  88.     }
  89.     m_TSEs[id_idx] = tse;
  90.     int count = ++m_TSEMap[tse];
  91.     if (count > 1) {
  92.         // One more ID found in a prefetched TSE
  93.         m_TSESemaphore.Post();
  94.     }
  95. }
  96. bool CPrefetchToken_Impl::IsEmpty(void) const
  97. {
  98.     CFastMutexGuard guard(m_Lock);
  99.     return m_Ids.empty();
  100. }
  101. CPrefetchToken_Impl::operator bool(void) const
  102. {
  103.     CFastMutexGuard guard(m_Lock);
  104.     return m_CurrentId < m_Ids.size();
  105. }
  106. CBioseq_Handle CPrefetchToken_Impl::NextBioseqHandle(CScope& scope)
  107. {
  108.     TTSE_Lock tse;
  109.     CSeq_id_Handle id;
  110.     {{
  111.         CFastMutexGuard guard(m_Lock);
  112.         // Can not call bool(*this) - creates deadlock
  113.         _ASSERT(m_CurrentId < m_Ids.size());
  114.         id = m_Ids[m_CurrentId];
  115.         // Keep temporary TSE lock
  116.         tse = m_TSEs[m_CurrentId];
  117.         m_TSEs[m_CurrentId].Reset();
  118.         ++m_CurrentId;
  119.         if ( tse ) {
  120.             TTSE_Map::iterator it = m_TSEMap.find(tse);
  121.             if ( --(it->second) < 1 ) {
  122.                 m_TSEMap.erase(it);
  123.                 // Signal that next TSE or next token may be prefetched
  124.                 m_TSESemaphore.Post();
  125.             }
  126.         }
  127.     }}
  128.     return scope.GetBioseqHandle(id);
  129. }
  130. void CPrefetchToken_Impl::AddTokenReference(void)
  131. {
  132.     ++m_TokenCount;
  133. }
  134. void CPrefetchToken_Impl::RemoveTokenReference(void)
  135. {
  136.     if ( !(--m_TokenCount) ) {
  137.         // No more tokens, reset the queue
  138.         CFastMutexGuard guard(m_Lock);
  139.         m_Ids.clear();
  140.         m_TSEs.clear();
  141.         m_CurrentId = 0;
  142.         // Allow the thread to process next token
  143.         m_TSESemaphore.Post();
  144.     }
  145. }
  146. CPrefetchThread::CPrefetchThread(CDataSource& data_source)
  147.     : m_DataSource(data_source),
  148.       m_Stop(false)
  149. {
  150.     return;
  151. }
  152. CPrefetchThread::~CPrefetchThread(void)
  153. {
  154.     return;
  155. }
  156. void CPrefetchThread::AddRequest(CPrefetchToken_Impl& token)
  157. {
  158.     {{
  159.         CFastMutexGuard guard(m_Lock);
  160.         m_Queue.Put(Ref(&token));
  161.     }}
  162. }
  163. void CPrefetchThread::Terminate(void)
  164. {
  165.     {{
  166.         CFastMutexGuard guard(m_Lock);
  167.         m_Stop = true;
  168.     }}
  169.     // Unlock the thread
  170.     m_Queue.Put(CRef<CPrefetchToken_Impl>(0));
  171. }
  172. void* CPrefetchThread::Main(void)
  173. {
  174.     do {
  175.         CRef<CPrefetchToken_Impl> token = m_Queue.Get();
  176.         {{
  177.             CFastMutexGuard guard(m_Lock);
  178.             if (m_Stop) {
  179.                 return 0;
  180.             }
  181.             _ASSERT( token );
  182.             if ( token->IsEmpty() ) {
  183.                 // Token may have been canceled
  184.                 continue;
  185.             }
  186.         }}
  187.         bool release_token = false;
  188.         for (size_t i = 0; ; ++i) {
  189.             {{
  190.                 CFastMutexGuard guard(m_Lock);
  191.                 if (m_Stop) {
  192.                     return 0;
  193.                 }
  194.             }}
  195.             CSeq_id_Handle id;
  196.             token->m_TSESemaphore.Wait();
  197.             {{
  198.                 // m_Ids may be cleaned up by the token, check size
  199.                 // on every iteration.
  200.                 CFastMutexGuard guard(token->m_Lock);
  201.                 i = max(i, token->m_CurrentId);
  202.                 if (i >= token->m_Ids.size()) {
  203.                     // Can not release token now - mutex is still locked
  204.                     release_token = true;
  205.                     break;
  206.                 }
  207.                 id = token->m_Ids[i];
  208.             }}
  209.             try {
  210.                 CSeqMatch_Info info = m_DataSource.BestResolve(id);
  211.                 if ( info ) {
  212.                     TTSE_Lock tse(&info.GetTSE_Info());
  213.                     if (tse) {
  214.                         token->AddResolvedId(i, tse);
  215.                     }
  216.                 }
  217.             } catch (...) {
  218.                 // BestResolve() failed, go to the next id.
  219.             }
  220.         }
  221.         if (release_token) {
  222.             token.Reset();
  223.         }
  224.     } while (true);
  225.     return 0;
  226. }
  227. END_SCOPE(objects)
  228. END_NCBI_SCOPE
  229. /*
  230. * ---------------------------------------------------------------------------
  231. * $Log: prefetch_impl.cpp,v $
  232. * Revision 1000.2  2004/06/01 19:23:32  gouriano
  233. * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.5
  234. *
  235. * Revision 1.5  2004/05/21 21:42:12  gorelenk
  236. * Added PCH ncbi_pch.hpp
  237. *
  238. * Revision 1.4  2004/05/07 13:47:35  grichenk
  239. * Removed single-id constructors.
  240. * Added non-locking prefetch mode.
  241. *
  242. * Revision 1.3  2004/04/26 14:15:33  grichenk
  243. * Catch exceptions in the prefetching thread
  244. *
  245. * Revision 1.2  2004/04/19 14:52:29  grichenk
  246. * Added prefetch depth limit, redesigned prefetch queue.
  247. *
  248. * Revision 1.1  2004/04/16 13:30:34  grichenk
  249. * Initial revision
  250. *
  251. *
  252. * ===========================================================================
  253. */