hmmer-3.3/easel/esl_dsqdata.c
/* Function:  esl_dsqdata_Close()
 * Synopsis:  Close a dsqdata reader.
 * Incept:    SRE, Thu Feb 11 19:32:54 2016
 *
 * Purpose:   Close a dsqdata reader.
 *
 * Returns:   <eslOK> on success.

 * Throws:    <eslESYS> on a system call failure, including pthread
 *            calls and fclose(). Caller should regard such a failure
 *            as disastrous: treat <dd> as toxic and exit as soon as 
 *            possible without making any other system calls, if possible.
 *            
 * Note: Normally Easel would call _Close() not only on a correctly
 *            opened object (after the Open returns) but also from
 *            within the Open call to clean up on failure. This relies
 *            on being able to tell which parts of an incomplete
 *            object have been initialized; this is why Easel sets
 *            ptrs to NULL before allocating them, for example.  POSIX
 *            threads doesn't seem to give us a way to check whether a
 *            mutex, condition variable, or thread has been
 *            initialized; and destroying an uninitialized mutex or CV
 *            results in undefined behavior. We could include a
 *            boolean flag for each pthreads component -- or one for
 *            all of them -- but instead, we simply say that a failure
 *            of pthreads initialization in the Open function is so
 *            catastrophic and unexpected that we exit that function
 *            without cleaning up the incomplete ESL_DSQDATA
 *            structure.  We expect that the caller is simply going to
 *            have to quit anyway, so we don't need to worry about
 *            memory leakage.
 */
esl_dsqdata_Close()
Synopsis:  Close a dsqdata reader.

Close a dsqdata reader.

 on success.

 on a system call failure, including pthread
calls and fclose(). Caller should regard such a failure
as disastrous: treat  as toxic and exit as soon as
possible without making any other system calls, if possible.

Normally Easel would call _Close() not only on a correctly
opened object (after the Open returns) but also from
within the Open call to clean up on failure. This relies
on being able to tell which parts of an incomplete
object have been initialized; this is why Easel sets
ptrs to NULL before allocating them, for example.  POSIX
threads doesn't seem to give us a way to check whether a
mutex, condition variable, or thread has been
initialized; and destroying an uninitialized mutex or CV
results in undefined behavior. We could include a
boolean flag for each pthreads component -- or one for
all of them -- but instead, we simply say that a failure
of pthreads initialization in the Open function is so
catastrophic and unexpected that we exit that function
without cleaning up the incomplete ESL_DSQDATA
structure.  We expect that the caller is simply going to
have to quit anyway, so we don't need to worry about
memory leakage.
esl_dsqdata_Close () Synopsis : Close a dsqdata reader . Close a dsqdata reader . on success . on a system call failure including pthread calls and fclose () . Caller should regard such a failure as disastrous : treat as toxic and exit as soon as possible without making any other system calls if possible . Normally Easel would call _Close () not only on a correctly opened object ( after the Open returns ) but also from within the Open call to clean up on failure . This relies on being able to tell which parts of an incomplete object have been initialized ; this is why Easel sets ptrs to NULL before allocating them for example . POSIX threads doesn ' t seem to give us a way to check whether a mutex condition variable or thread has been initialized ; and destroying an uninitialized mutex or CV results in undefined behavior . We could include a boolean flag for each pthreads component -- or one for all of them -- but instead we simply say that a failure of pthreads initialization in the Open function is so catastrophic and unexpected that we exit that function without cleaning up the incomplete ESL_DSQDATA structure . We expect that the caller is simply going to have to quit anyway so we don ' t need to worry about memory leakage .
int
esl_dsqdata_Close(ESL_DSQDATA *dd)
{
  int u;
  if (dd)
    {
      if ( pthread_join(dd->loader_t,   NULL)      != 0)  ESL_EXCEPTION(eslESYS, "pthread join failed");          
      for (u = 0; u < dd->n_unpackers; u++)
	if ( pthread_join(dd->unpacker_t[u], NULL) != 0)  ESL_EXCEPTION(eslESYS, "pthread join failed");          
      if (dd->basename) free(dd->basename);
      if (dd->stubfp) { if ( fclose(dd->stubfp) != 0) ESL_EXCEPTION(eslESYS, "fclose failed"); }
      if (dd->ifp)    { if ( fclose(dd->ifp)    != 0) ESL_EXCEPTION(eslESYS, "fclose failed"); }
      if (dd->sfp)    { if ( fclose(dd->sfp)    != 0) ESL_EXCEPTION(eslESYS, "fclose failed"); }
      if (dd->mfp)    { if ( fclose(dd->mfp)    != 0) ESL_EXCEPTION(eslESYS, "fclose failed"); }
      for (u = 0; u < dd->n_unpackers; u++)
	{
	  if ( pthread_mutex_destroy(&(dd->inbox_mutex[u]))  != 0)  ESL_EXCEPTION(eslESYS, "pthread mutex destroy failed"); 
	  if ( pthread_cond_destroy(&(dd->inbox_cv[u]))      != 0)  ESL_EXCEPTION(eslESYS, "pthread cond destroy failed");  
	  if ( pthread_mutex_destroy(&(dd->outbox_mutex[u])) != 0)  ESL_EXCEPTION(eslESYS, "pthread mutex destroy failed"); 
	  if ( pthread_cond_destroy(&(dd->outbox_cv[u]))     != 0)  ESL_EXCEPTION(eslESYS, "pthread cond destroy failed"); 
	}
      if ( pthread_mutex_destroy(&dd->nchunk_mutex)          != 0)  ESL_EXCEPTION(eslESYS, "pthread mutex destroy failed"); 
      if ( pthread_mutex_destroy(&dd->recycling_mutex)       != 0)  ESL_EXCEPTION(eslESYS, "pthread mutex destroy failed"); 
      if ( pthread_cond_destroy(&dd->recycling_cv)           != 0)  ESL_EXCEPTION(eslESYS, "pthread cond destroy failed");  
      if ( pthread_mutex_destroy(&dd->go_mutex)              != 0)  ESL_EXCEPTION(eslESYS, "pthread mutex destroy failed"); 
      if ( pthread_cond_destroy(&dd->go_cv)                  != 0)  ESL_EXCEPTION(eslESYS, "pthread cond destroy failed");  
#if (eslDEBUGLEVEL >= 1)
      for (u = 0; u < dd->n_unpackers; u++) {
	assert( dd->inbox[u]  == NULL );
	assert( dd->outbox[u] == NULL );
      }
      assert(dd->recycling == NULL );
#endif
      free(dd);
    }
  return eslOK;
}
int esl_dsqdata_Close ( ESL_DSQDATA * dd ) { int u ; if ( dd ) { if ( pthread_join ( dd -> loader_t , NULL ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; for ( u = 0 ; u < dd -> n_unpackers ; u ++ ) if ( pthread_join ( dd -> unpacker_t [ u ] , NULL ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( dd -> basename ) free ( dd -> basename ) ; if ( dd -> stubfp ) { if ( fclose ( dd -> stubfp ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; } if ( dd -> ifp ) { if ( fclose ( dd -> ifp ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; } if ( dd -> sfp ) { if ( fclose ( dd -> sfp ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; } if ( dd -> mfp ) { if ( fclose ( dd -> mfp ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; } for ( u = 0 ; u < dd -> n_unpackers ; u ++ ) { if ( pthread_mutex_destroy ( & ( dd -> inbox_mutex [ u ] ) ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_cond_destroy ( & ( dd -> inbox_cv [ u ] ) ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_mutex_destroy ( & ( dd -> outbox_mutex [ u ] ) ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_cond_destroy ( & ( dd -> outbox_cv [ u ] ) ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; } if ( pthread_mutex_destroy ( & dd -> nchunk_mutex ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_mutex_destroy ( & dd -> recycling_mutex ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_cond_destroy ( & dd -> recycling_cv ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_mutex_destroy ( & dd -> go_mutex ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; if ( pthread_cond_destroy ( & dd -> go_cv ) != 0 ) ESL_EXCEPTION ( eslESYS , " " ) ; #if ( eslDEBUGLEVEL >= 1 ) for ( u = 0 ; u < dd -> n_unpackers ; u ++ ) { assert ( dd -> inbox [ u ] == NULL ) ; assert ( dd -> outbox [ u ] == NULL ) ; } assert ( dd -> recycling == NULL ) ; #endif free ( dd ) ; } return eslOK ; }
Function:  esl_dsqdata_Close()
 Synopsis:  Close a dsqdata reader.
Function : esl_dsqdata_Close () Synopsis : Close a dsqdata reader .
/* out of abundance of caution - wait for threads to join before breaking down <dd> */ /* Loader thread is responsible for freeing all chunks it created, even on error. */