CppAD: A C++ Algorithmic Differentiation Package
20130102
|
00001 /* $Id$ */ 00002 # ifndef CPPAD_THREAD_ALLOC_INCLUDED 00003 # define CPPAD_THREAD_ALLOC_INCLUDED 00004 00005 /* -------------------------------------------------------------------------- 00006 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-12 Bradley M. Bell 00007 00008 CppAD is distributed under multiple licenses. This distribution is under 00009 the terms of the 00010 Eclipse Public License Version 1.0. 00011 00012 A copy of this license is included in the COPYING file of this distribution. 00013 Please visit http://www.coin-or.org/CppAD/ for information on other licenses. 00014 -------------------------------------------------------------------------- */ 00015 00016 # include <sstream> 00017 # include <limits> 00018 # include <memory> 00019 00020 00021 # ifdef _MSC_VER 00022 // Supress warning that Microsoft compiler changed its behavior and is now 00023 // doing the correct thing at the statement: 00024 // new(array + i) Type(); 00025 # pragma warning(disable:4345) 00026 # endif 00027 00028 # include <cppad/local/cppad_assert.hpp> 00029 # include <cppad/local/define.hpp> 00030 CPPAD_BEGIN_NAMESPACE 00031 /*! 00032 \defgroup thread_alloc_hpp thread_alloc.hpp 00033 \{ 00034 \file thread_alloc.hpp 00035 File used to define the CppAD multi-threading allocaor class 00036 */ 00037 00038 /*! 00039 \def CPPAD_MAX_NUM_CAPACITY 00040 Maximum number of different capacities the allocator will attempt. 00041 This must be larger than the log base two of numeric_limit<size_t>::max(). 00042 */ 00043 # define CPPAD_MAX_NUM_CAPACITY 100 00044 00045 /*! 00046 \def CPPAD_MIN_DOUBLE_CAPACITY 00047 Minimum number of double values that will fit in an allocation. 00048 */ 00049 # define CPPAD_MIN_DOUBLE_CAPACITY 16 00050 00051 /*! 00052 \def CPPAD_TRACE_CAPACITY 00053 If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory 00054 that correspond to this capacity and thread CPPAD_TRACE_THEAD. 00055 (Note that if CPPAD_TRACE_CAPACITY is zero, or any other value not in the list 00056 of capacities, no tracing will be done.) 00057 */ 00058 # define CPPAD_TRACE_CAPACITY 0 00059 00060 /*! 00061 \def CPPAD_TRACE_THREAD 00062 If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory 00063 that correspond to this thead and capacity CPPAD_TRACE_CAPACITY. 00064 */ 00065 # define CPPAD_TRACE_THREAD 0 00066 00067 /* 00068 Note that Section 3.6.2 of ISO/IEC 14882:1998(E) states: "The storage for 00069 objects with static storage duration (3.7.1) shall be zero-initialized 00070 (8.5) before any other initialization takes place." 00071 */ 00072 00073 /*! 00074 Capacity vector for memory allocation block sizes. 00075 00076 Only one of these objects should be created and used as a 00077 static variable inside of the \c thread_alloc::capacity_info function. 00078 */ 00079 00080 /*! 00081 Allocator class that works well with an multi-threading environment. 00082 */ 00083 class thread_alloc{ 00084 // ============================================================================ 00085 private: 00086 00087 class capacity_t { 00088 public: 00089 /// number of capacity values actually used 00090 size_t number; 00091 /// the different capacity values 00092 size_t value[CPPAD_MAX_NUM_CAPACITY]; 00093 /// ctor 00094 capacity_t(void) 00095 { // Cannot figure out how to call thread_alloc::in_parallel here. 00096 // CPPAD_ASSERT_UNKNOWN( 00097 // ! thread_alloc::in_parallel() , "thread_alloc: " 00098 // "parallel mode and parallel_setup not yet called." 00099 // ); 00100 number = 0; 00101 size_t capacity = CPPAD_MIN_DOUBLE_CAPACITY * sizeof(double); 00102 while( capacity < std::numeric_limits<size_t>::max() / 2 ) 00103 { CPPAD_ASSERT_UNKNOWN( number < CPPAD_MAX_NUM_CAPACITY ); 00104 value[number++] = capacity; 00105 // next capactiy is 3/2 times the current one 00106 capacity = 3 * ( (capacity + 1) / 2 ); 00107 } 00108 CPPAD_ASSERT_UNKNOWN( number > 0 ); 00109 } 00110 }; 00111 00112 class block_t { 00113 public: 00114 /// extra information (currently used by create and delete array) 00115 size_t extra_; 00116 /// an index that uniquely idenfifies both thread and capacity 00117 size_t tc_index_; 00118 /// pointer to the next memory allocation with the the same tc_index_ 00119 void* next_; 00120 // ----------------------------------------------------------------- 00121 /// make default constructor private. It is only used by constructor 00122 /// for `root arrays below. 00123 block_t(void) : extra_(0), tc_index_(0), next_(0) 00124 { } 00125 }; 00126 00127 // --------------------------------------------------------------------- 00128 /// Vector of fixed capacity values for this allocator 00129 static const capacity_t* capacity_info(void) 00130 { CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; 00131 static const capacity_t capacity; 00132 return &capacity; 00133 } 00134 // --------------------------------------------------------------------- 00135 /// Structure of information for each thread 00136 struct thread_alloc_info { 00137 /// count of available bytes for this thread 00138 size_t count_inuse_; 00139 /// count of inuse bytes for this thread 00140 size_t count_available_; 00141 /// root of available list for this thread and each capacity 00142 block_t root_available_[CPPAD_MAX_NUM_CAPACITY]; 00143 /// root of inuse list for this thread and each capacity 00144 /// If NDEBUG is true, this memory is not used, but it still 00145 /// helps separate this structure from one for the next thread. 00146 block_t root_inuse_[CPPAD_MAX_NUM_CAPACITY]; 00147 }; 00148 // --------------------------------------------------------------------- 00149 /*! 00150 Set and Get hold available memory flag. 00151 00152 \param set [in] 00153 if true, the value returned by this return is changed. 00154 00155 \param new_value [in] 00156 if \a set is true, this is the new value returned by this routine. 00157 Otherwise, \c new_value is ignored. 00158 00159 \return 00160 the current setting for this routine (which is initially false). 00161 */ 00162 static bool set_get_hold_memory(bool set, bool new_value = false) 00163 { static bool value = false; 00164 if( set ) 00165 value = new_value; 00166 return value; 00167 } 00168 // --------------------------------------------------------------------- 00169 /*! 00170 Get pointer to the information for this thread. 00171 00172 \param thread [in] 00173 Is the thread number for this information pointer. 00174 00175 \param clear 00176 If \a clear is true, then the information pointer for this thread 00177 is deleted and the \c CPPAD_NULL pointer is returned. 00178 There must be no memory currently in either the inuse or avaialble 00179 lists when this routine is called. 00180 00181 \return 00182 is the current informaiton pointer for this thread. 00183 If \a clear is false, and the current pointer is CPPAD_NULL, 00184 a new infromation record is allocated and its pointer returned. 00185 In this case, if \c info is the retured pointer, 00186 <code>info->count_inuse == 0</code> and 00187 <code>info->count_available == 0</code>. 00188 In addition, 00189 for <code>c = 0 , ... , CPPAD_MAX_NUM_CAPACITY-1</code> 00190 <code>info->root_inuse_[c].next_ == CPPAD_NULL</code> and 00191 <code>info->root_available_[c].next_ == CPPAD_NULL</code>. 00192 */ 00193 static thread_alloc_info* thread_info( 00194 size_t thread , 00195 bool clear = false ) 00196 { static thread_alloc_info* all_info[CPPAD_MAX_NUM_THREADS]; 00197 static thread_alloc_info zero_info; 00198 00199 CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; 00200 00201 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS ); 00202 00203 thread_alloc_info* info = all_info[thread]; 00204 if( clear ) 00205 { if( info != CPPAD_NULL ) 00206 { 00207 # ifndef NDEBUG 00208 CPPAD_ASSERT_UNKNOWN( 00209 info->count_inuse_ == 0 && 00210 info->count_available_ == 0 00211 ); 00212 for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++) 00213 { CPPAD_ASSERT_UNKNOWN( 00214 info->root_inuse_[c].next_ == CPPAD_NULL && 00215 info->root_available_[c].next_ == CPPAD_NULL 00216 ); 00217 } 00218 # endif 00219 if( thread != 0 ) 00220 ::operator delete( reinterpret_cast<void*>(info) ); 00221 info = CPPAD_NULL; 00222 all_info[thread] = info; 00223 } 00224 } 00225 else if( info == CPPAD_NULL ) 00226 { if( thread == 0 ) 00227 info = &zero_info; 00228 else 00229 { size_t size = sizeof(thread_alloc_info); 00230 void* v_ptr = ::operator new(size); 00231 info = reinterpret_cast<thread_alloc_info*>(v_ptr); 00232 } 00233 all_info[thread] = info; 00234 00235 // initialize the information record 00236 for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++) 00237 { info->root_inuse_[c].next_ = CPPAD_NULL; 00238 info->root_available_[c].next_ = CPPAD_NULL; 00239 } 00240 info->count_inuse_ = 0; 00241 info->count_available_ = 0; 00242 } 00243 return info; 00244 } 00245 // ----------------------------------------------------------------------- 00246 /*! 00247 Increase the number of bytes of memory that are currently in use; i.e., 00248 that been obtained with \c get_memory and not yet returned. 00249 00250 \param inc [in] 00251 amount to increase memory in use. 00252 00253 \param thread [in] 00254 Thread for which we are increasing the number of bytes in use 00255 (must be less than \c num_threads). 00256 Durring parallel execution, this must be the thread 00257 that is currently executing. 00258 */ 00259 static void inc_inuse(size_t inc, size_t thread) 00260 { 00261 CPPAD_ASSERT_UNKNOWN( thread < num_threads() ); 00262 CPPAD_ASSERT_UNKNOWN( 00263 thread == thread_num() || (! in_parallel()) 00264 ); 00265 thread_alloc_info* info = thread_info(thread); 00266 00267 // do the addition 00268 size_t result = info->count_inuse_ + inc; 00269 CPPAD_ASSERT_UNKNOWN( result >= info->count_inuse_ ); 00270 00271 info->count_inuse_ = result; 00272 } 00273 // ----------------------------------------------------------------------- 00274 /*! 00275 Increase the number of bytes of memory that are currently avaialble; i.e., 00276 have been obtained obtained from the system and are being held future use. 00277 00278 \copydetails inc_inuse 00279 */ 00280 static void inc_available(size_t inc, size_t thread) 00281 { 00282 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); 00283 CPPAD_ASSERT_UNKNOWN( 00284 thread == thread_num() || (! in_parallel()) 00285 ); 00286 thread_alloc_info* info = thread_info(thread); 00287 // do the addition 00288 size_t result = info->count_available_ + inc; 00289 CPPAD_ASSERT_UNKNOWN( result >= info->count_available_ ); 00290 00291 info->count_available_ = result; 00292 } 00293 // ----------------------------------------------------------------------- 00294 /*! 00295 Decrease the number of bytes of memory that are currently in use; i.e., 00296 that been obtained with \c get_memory and not yet returned. 00297 00298 \param dec [in] 00299 amount to decrease number of bytes in use. 00300 00301 \param thread [in] 00302 Thread for which we are decreasing the number of bytes in use 00303 (must be less than \c num_threads). 00304 Durring parallel execution, this must be the thread 00305 that is currently executing. 00306 */ 00307 static void dec_inuse(size_t dec, size_t thread) 00308 { 00309 CPPAD_ASSERT_UNKNOWN( 00310 thread < num_threads() || (! in_parallel()) 00311 ); 00312 CPPAD_ASSERT_UNKNOWN( 00313 thread == thread_num() || (! in_parallel()) 00314 ); 00315 thread_alloc_info* info = thread_info(thread); 00316 00317 // do the subtraction 00318 CPPAD_ASSERT_UNKNOWN( info->count_inuse_ >= dec ); 00319 info->count_inuse_ = info->count_inuse_ - dec; 00320 } 00321 // ----------------------------------------------------------------------- 00322 /*! 00323 Decrease the number of bytes of memory that are currently avaialble; i.e., 00324 have been obtained obtained from the system and are being held future use. 00325 00326 \copydetails dec_inuse 00327 */ 00328 static void dec_available(size_t dec, size_t thread) 00329 { 00330 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); 00331 CPPAD_ASSERT_UNKNOWN( 00332 thread == thread_num() || (! in_parallel()) 00333 ); 00334 thread_alloc_info* info = thread_info(thread); 00335 // do the subtraction 00336 CPPAD_ASSERT_UNKNOWN( info->count_available_ >= dec ); 00337 info->count_available_ = info->count_available_ - dec; 00338 } 00339 00340 // ---------------------------------------------------------------------- 00341 /*! 00342 Set and get the number of threads that are sharing memory. 00343 00344 \param number_new 00345 If \c number is zero, we are only retreiving the current maximum 00346 number of threads. Otherwise, we are setting and retreiving 00347 maximum number of threads. 00348 00349 \return 00350 the number of threads that are sharing memory. 00351 If \c number_new is non-zero, the return value is equal to 00352 \c number_new. 00353 */ 00354 static size_t set_get_num_threads(size_t number_new) 00355 { static size_t number_user = 1; 00356 00357 CPPAD_ASSERT_UNKNOWN( number_new <= CPPAD_MAX_NUM_THREADS ); 00358 CPPAD_ASSERT_UNKNOWN( ! in_parallel() || (number_new == 0) ); 00359 00360 // case where we are changing the number of threads 00361 if( number_new != 0 ) 00362 number_user = number_new; 00363 00364 return number_user; 00365 } 00366 /*! 00367 Set and call the routine that determine if we are in parallel 00368 execution mode. 00369 00370 \return 00371 value retuned by most recent setting for \a parallel_new. 00372 If \a set is true, 00373 or the most recent setting is \c CPPAD_NULL (its initial value), 00374 the return value is false. 00375 Otherwise the function corresponding to the most recent setting 00376 is called and its value returned by \c set_get_in_parallel. 00377 00378 \param parallel_new [in] 00379 If \a set is false, \a parallel_new it is not used. 00380 Otherwise, the current value of \c parallel_new becomes the 00381 most recent setting for in_parallel. 00382 00383 \param set 00384 If \a set is true, then \a parallel_new is becomes the most 00385 recent setting for this \c set_get_in_parallel. 00386 */ 00387 static bool set_get_in_parallel( 00388 bool (*parallel_new)(void) , 00389 bool set = false ) 00390 { static bool (*parallel_user)(void) = CPPAD_NULL; 00391 00392 if( set ) 00393 { parallel_user = parallel_new; 00394 return false; 00395 } 00396 00397 if( parallel_user == CPPAD_NULL ) 00398 return false; 00399 00400 return parallel_user(); 00401 } 00402 /*! 00403 Set and call the routine that determine the current thread number. 00404 00405 \return 00406 returns value for the most recent setting for \a thread_num_new. 00407 If \a set is true, 00408 or the most recent setting is \c CPPAD_NULL (its initial value), 00409 the return value is zero. 00410 Otherwise the routine corresponding to the most recent setting 00411 is called and its value returned by \c set_get_thread_num. 00412 00413 \param thread_num_new [in] 00414 If \a set is false, \a thread_num_new it is not used. 00415 Otherwise, the current value of \c thread_num_new becomes the 00416 most recent setting for thread_num. 00417 00418 \param set 00419 If \a set is true, then \a thread_num_new is becomes the most 00420 recent setting for this \c set_get_thread_num. 00421 */ 00422 static size_t set_get_thread_num( 00423 size_t (*thread_num_new)(void) , 00424 bool set = false ) 00425 { static size_t (*thread_num_user)(void) = CPPAD_NULL; 00426 00427 if( set ) 00428 { thread_num_user = thread_num_new; 00429 return 0; 00430 } 00431 00432 if( thread_num_user == CPPAD_NULL ) 00433 return 0; 00434 00435 size_t thread = thread_num_user(); 00436 CPPAD_ASSERT_KNOWN( 00437 thread < set_get_num_threads(0) , 00438 "parallel_setup: thread_num() >= num_threads" 00439 ); 00440 return thread; 00441 } 00442 // ============================================================================ 00443 public: 00444 /* 00445 $begin ta_parallel_setup$$ 00446 $spell 00447 alloc 00448 num 00449 bool 00450 $$ 00451 $section Setup thread_alloc For Use in Multi-Threading Environment$$ 00452 00453 $index setup, thread_alloc$$ 00454 $index thread_alloc, setup$$ 00455 $index parallel, setup$$ 00456 $index setup, parallel$$ 00457 00458 $index num_threads$$ 00459 $index in_parallel$$ 00460 $index thread_num$$ 00461 00462 $index multi-threading, initialize$$ 00463 $index initialize, multi-threading$$ 00464 00465 $head Syntax$$ 00466 $codei%thread_alloc::parallel_setup(%num_threads%, %in_parallel%, %thread_num%) 00467 %$$ 00468 00469 $head Purpose$$ 00470 By default there is only one thread and all execution is in sequential mode, 00471 i.e., multiple threads are not sharing the same memory; i.e. 00472 not in parallel mode. 00473 00474 $head Speed$$ 00475 It should be faster, even when $icode num_thread$$ is equal to one, 00476 for $code thread_alloc$$ to hold onto memory. 00477 This can be accomplished using the function call 00478 $codei% 00479 thread_alloc::hold_memory(true) 00480 %$$ 00481 see $cref/hold_memory/ta_hold_memory/$$. 00482 00483 $head num_threads$$ 00484 This argument has prototype 00485 $codei% 00486 size_t %num_threads% 00487 %$$ 00488 and must be greater than zero. 00489 It specifies the number of threads that are sharing memory. 00490 The case $icode%num_threads% == 1%$$ is a special case that is 00491 used to terminate a multi-threading environment. 00492 00493 $head in_parallel$$ 00494 This function has prototype 00495 $codei% 00496 bool %in_parallel%(void) 00497 %$$ 00498 It must return $code true$$ if there is more than one thread 00499 currently executing. 00500 Otherwise it can return false. 00501 $pre 00502 00503 $$ 00504 In the special case where $icode%num_threads% == 1%$$, 00505 the routine $icode in_parallel$$ is not used. 00506 00507 $head thread_num$$ 00508 This function has prototype 00509 $codei% 00510 size_t %thread_num%(void) 00511 %$$ 00512 It must return a thread number that uniquely identifies the 00513 currently executing thread. 00514 Furthermore 00515 $codei% 00516 0 <= %thread_num%() < %num_threads% 00517 %$$. 00518 In the special case where $icode%num_threads% == 1%$$, 00519 the routine $icode thread_num$$ is not used. 00520 $pre 00521 00522 $$ 00523 Note that this function is called by other routines so, 00524 as soon as a new thread is executing, 00525 one must be certain that $icode thread_num()$$ will 00526 work for that thread. 00527 00528 $head Restrictions$$ 00529 The function $code parallel_setup$$ must be called before 00530 the program enters $cref/parallel/ta_in_parallel/$$ execution mode. 00531 In addition, this function cannot be called while in parallel mode. 00532 00533 $head Example$$ 00534 The files 00535 $cref simple_ad_openmp.cpp$$, 00536 $cref simple_ad_bthread.cpp$$, and 00537 $cref simple_ad_pthread.cpp$$, 00538 contain examples and tests that use this function. 00539 00540 $end 00541 */ 00542 /*! 00543 Set thread_alloc up for parallel mode usage. 00544 00545 \param num_threads [in] 00546 Is the number of thread that may be executing at the same time. 00547 00548 \param in_parallel [in] 00549 Is the routine that determines if we are in parallel mode or not. 00550 00551 \param thread_num [in] 00552 Is the routine that determines the current thread number 00553 (between zero and num_threads minus one). 00554 */ 00555 static void parallel_setup( 00556 size_t num_threads , 00557 bool (*in_parallel)(void) , 00558 size_t (*thread_num)(void) ) 00559 { 00560 // Special case where we go back to single thread mode right away 00561 // (previous settings may no longer be valid) 00562 if( num_threads == 1 ) 00563 { bool set = true; 00564 set_get_num_threads(num_threads); 00565 set_get_in_parallel(CPPAD_NULL, set); 00566 set_get_thread_num(CPPAD_NULL, set); 00567 return; 00568 } 00569 00570 CPPAD_ASSERT_KNOWN( 00571 num_threads <= CPPAD_MAX_NUM_THREADS , 00572 "parallel_setup: num_threads is too large" 00573 ); 00574 CPPAD_ASSERT_KNOWN( 00575 num_threads != 0 , 00576 "parallel_setup: num_threads == zero" 00577 ); 00578 CPPAD_ASSERT_KNOWN( 00579 in_parallel != CPPAD_NULL , 00580 "parallel_setup: num_threads != 1 and in_parallel == CPPAD_NULL" 00581 ); 00582 CPPAD_ASSERT_KNOWN( 00583 thread_num != CPPAD_NULL , 00584 "parallel_setup: num_threads != 1 and thread_num == CPPAD_NULL" 00585 ); 00586 00587 // Make sure that constructors for all static variables in this file 00588 // are called in sequential mode. 00589 for(size_t thread = 0; thread < num_threads; thread++) 00590 thread_info(thread); 00591 capacity_info(); 00592 size_t cap_bytes; 00593 void* v_ptr = get_memory(0, cap_bytes); 00594 00595 // free memory allocated by call to get_memory above 00596 return_memory(v_ptr); 00597 free_available( set_get_thread_num(CPPAD_NULL) ); 00598 00599 // delay this so thread_num() call above is in previous mode 00600 // (current setings may not yet be valid) 00601 if( num_threads > 1 ) 00602 { bool set = true; 00603 set_get_num_threads(num_threads); 00604 set_get_in_parallel(in_parallel, set); 00605 set_get_thread_num(thread_num, set); 00606 } 00607 } 00608 /* 00609 $begin ta_num_threads$$ 00610 $spell 00611 inv 00612 CppAD 00613 num 00614 alloc 00615 $$ 00616 $section Get Number of Threads$$ 00617 00618 $index num_threads, thread_alloc$$ 00619 $index thread_alloc, num_threads$$ 00620 $index threads, number of$$ 00621 00622 $head Syntax$$ 00623 $icode%number% = thread_alloc::num_threads()%$$ 00624 00625 $head Purpose$$ 00626 Determine the number of threads as set during $cref/parallel_setup/ta_parallel_setup/$$. 00627 00628 $head number$$ 00629 The return value $icode number$$ has prototype 00630 $icode% 00631 size_t %number% 00632 %$$ 00633 and is equal to the value of 00634 $cref/num_threads/ta_parallel_setup/num_threads/$$ 00635 in the previous call to $icode parallel_setup$$. 00636 If there was no such previous call, the value one is returned. 00637 00638 $head Example$$ 00639 The example and test $cref thread_alloc.cpp$$ uses this routine. 00640 00641 $end 00642 */ 00643 /*! 00644 Get the current number of threads that thread_alloc can use. 00645 */ 00646 static size_t num_threads(void) 00647 { return set_get_num_threads(0); } 00648 /* ----------------------------------------------------------------------- 00649 $begin ta_in_parallel$$ 00650 00651 $section Is The Current Execution in Parallel Mode$$ 00652 $spell 00653 thread_alloc 00654 bool 00655 $$ 00656 00657 $index in_parallel, thread_alloc$$ 00658 $index thread_alloc, in_parallel$$ 00659 $index parallel, execution$$ 00660 $index execution, parallel$$ 00661 $index sequential, execution$$ 00662 00663 $head Syntax$$ 00664 $icode%flag% = thread_alloc::in_parallel()%$$ 00665 00666 $head Purpose$$ 00667 Some of the $cref thread_alloc$$ allocation routines have different 00668 specifications for parallel (not sequential) execution mode. 00669 This routine enables you to determine if the current execution mode 00670 is sequential or parallel. 00671 00672 $head flag$$ 00673 The return value has prototype 00674 $codei% 00675 bool %flag% 00676 %$$ 00677 It is true if the current execution is in parallel mode 00678 (possibly multi-threaded) and false otherwise (sequential mode). 00679 00680 $head Example$$ 00681 $cref thread_alloc.cpp$$ 00682 00683 $end 00684 */ 00685 /// Are we in a parallel execution state; i.e., is it possible that 00686 /// other threads are currently executing. 00687 static bool in_parallel(void) 00688 { return set_get_in_parallel(0); } 00689 /* ----------------------------------------------------------------------- 00690 $begin ta_thread_num$$ 00691 $spell 00692 CppAD 00693 num 00694 thread_alloc 00695 cppad.hpp 00696 $$ 00697 00698 $section Get the Current Thread Number$$ 00699 00700 $index thread_num, thread_alloc$$ 00701 $index thread_alloc, thread_num$$ 00702 $index thread, current$$ 00703 $index current, thread$$ 00704 00705 $head Syntax$$ 00706 $icode%thread% = thread_alloc::thread_num()%$$ 00707 00708 $head Purpose$$ 00709 Some of the $cref thread_alloc$$ allocation routines have a thread number. 00710 This routine enables you to determine the current thread. 00711 00712 $head thread$$ 00713 The return value $icode thread$$ has prototype 00714 $codei% 00715 size_t %thread% 00716 %$$ 00717 and is the currently executing thread number. 00718 If $code _OPENMP$$ is not defined, $icode thread$$ is zero. 00719 00720 $head Example$$ 00721 $cref thread_alloc.cpp$$ 00722 00723 $end 00724 */ 00725 /// Get current thread number 00726 static size_t thread_num(void) 00727 { return set_get_thread_num(CPPAD_NULL); } 00728 /* ----------------------------------------------------------------------- 00729 $begin ta_get_memory$$ 00730 $spell 00731 num 00732 ptr 00733 thread_alloc 00734 $$ 00735 00736 $section Get At Least A Specified Amount of Memory$$ 00737 00738 $index thread_num, thread_alloc$$ 00739 $index thread_alloc, thread_num$$ 00740 $index memory, allocate$$ 00741 $index allocate, memory$$ 00742 00743 $head Syntax$$ 00744 $icode%v_ptr% = thread_alloc::get_memory(%min_bytes%, %cap_bytes%)%$$ 00745 00746 $head Purpose$$ 00747 Use $cref thread_alloc$$ to obtain a minimum number of bytes of memory 00748 (for use by the $cref/current thread/ta_thread_num/$$). 00749 00750 $head min_bytes$$ 00751 This argument has prototype 00752 $codei% 00753 size_t %min_bytes% 00754 %$$ 00755 It specifies the minimum number of bytes to allocate. 00756 00757 $head cap_bytes$$ 00758 This argument has prototype 00759 $codei% 00760 size_t& %cap_bytes% 00761 %$$ 00762 It's input value does not matter. 00763 Upon return, it is the actual number of bytes (capacity) 00764 that have been allocated for use, 00765 $codei% 00766 %min_bytes% <= %cap_bytes% 00767 %$$ 00768 00769 $head v_ptr$$ 00770 The return value $icode v_ptr$$ has prototype 00771 $codei% 00772 void* %v_ptr% 00773 %$$ 00774 It is the location where the $icode cap_bytes$$ of memory 00775 that have been allocated for use begins. 00776 00777 $head Allocation Speed$$ 00778 This allocation should be faster if the following conditions hold: 00779 $list number$$ 00780 The memory allocated by a previous call to $code get_memory$$ 00781 is currently available for use. 00782 $lnext 00783 The current $icode min_bytes$$ is between 00784 the previous $icode min_bytes$$ and previous $icode cap_bytes$$. 00785 $lend 00786 00787 $head Example$$ 00788 $cref thread_alloc.cpp$$ 00789 00790 $end 00791 */ 00792 /*! 00793 Use thread_alloc to get a specified amount of memory. 00794 00795 If the memory allocated by a previous call to \c get_memory is now 00796 avaialable, and \c min_bytes is between its previous value 00797 and the previous \c cap_bytes, this memory allocation will have 00798 optimal speed. Otherwise, the memory allocation is more complicated and 00799 may have to wait for other threads to complete an allocation. 00800 00801 \param min_bytes [in] 00802 The minimum number of bytes of memory to be obtained for use. 00803 00804 \param cap_bytes [out] 00805 The actual number of bytes of memory obtained for use. 00806 00807 \return 00808 pointer to the beginning of the memory allocated for use. 00809 */ 00810 static void* get_memory(size_t min_bytes, size_t& cap_bytes) 00811 { // see first_trace below 00812 CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL; 00813 00814 size_t num_cap = capacity_info()->number; 00815 using std::cout; 00816 using std::endl; 00817 00818 // determine the capacity for this request 00819 size_t c_index = 0; 00820 const size_t* capacity_vec = capacity_info()->value; 00821 while( capacity_vec[c_index] < min_bytes ) 00822 { ++c_index; 00823 CPPAD_ASSERT_UNKNOWN(c_index < num_cap ); 00824 } 00825 cap_bytes = capacity_vec[c_index]; 00826 00827 // determine the thread, capacity, and info for this thread 00828 size_t thread = thread_num(); 00829 size_t tc_index = thread * num_cap + c_index; 00830 thread_alloc_info* info = thread_info(thread); 00831 00832 # ifndef NDEBUG 00833 // trace allocation 00834 static bool first_trace = true; 00835 if( cap_bytes == CPPAD_TRACE_CAPACITY && 00836 thread == CPPAD_TRACE_THREAD && first_trace ) 00837 { cout << endl; 00838 cout << "thread_alloc: Trace for Thread = " << thread; 00839 cout << " and capacity = " << cap_bytes << endl; 00840 if( first_trace ) 00841 first_trace = false; 00842 } 00843 00844 // Root nodes for both lists. Note these are different for different 00845 // threads because tc_index is different for different threads. 00846 block_t* inuse_root = info->root_inuse_ + c_index; 00847 # endif 00848 block_t* available_root = info->root_available_ + c_index; 00849 00850 // check if we already have a node we can use 00851 void* v_node = available_root->next_; 00852 block_t* node = reinterpret_cast<block_t*>(v_node); 00853 if( node != 0 ) 00854 { CPPAD_ASSERT_UNKNOWN( node->tc_index_ == tc_index ); 00855 00856 // remove node from available list 00857 available_root->next_ = node->next_; 00858 00859 // return value for get_memory 00860 void* v_ptr = reinterpret_cast<void*>(node + 1); 00861 # ifndef NDEBUG 00862 // add node to inuse list 00863 node->next_ = inuse_root->next_; 00864 inuse_root->next_ = v_node; 00865 00866 // trace allocation 00867 if( cap_bytes == CPPAD_TRACE_CAPACITY && 00868 thread == CPPAD_TRACE_THREAD ) 00869 { cout << "get_memory: v_ptr = " << v_ptr << endl; } 00870 # endif 00871 00872 // adjust counts 00873 inc_inuse(cap_bytes, thread); 00874 dec_available(cap_bytes, thread); 00875 00876 // return pointer to memory, do not inclue thread_alloc information 00877 return v_ptr; 00878 } 00879 00880 // Create a new node with thread_alloc information at front. 00881 // This uses the system allocator, which is thread safe, but slower, 00882 // because the thread might wait for a lock on the allocator. 00883 v_node = ::operator new(sizeof(block_t) + cap_bytes); 00884 node = reinterpret_cast<block_t*>(v_node); 00885 node->tc_index_ = tc_index; 00886 void* v_ptr = reinterpret_cast<void*>(node + 1); 00887 00888 # ifndef NDEBUG 00889 // add node to inuse list 00890 node->next_ = inuse_root->next_; 00891 inuse_root->next_ = v_node; 00892 00893 // trace allocation 00894 if( cap_bytes == CPPAD_TRACE_CAPACITY && 00895 thread == CPPAD_TRACE_THREAD ) 00896 { cout << "get_memory: v_ptr = " << v_ptr << endl; } 00897 # endif 00898 00899 // adjust counts 00900 inc_inuse(cap_bytes, thread); 00901 00902 return v_ptr; 00903 } 00904 00905 /* ----------------------------------------------------------------------- 00906 $begin ta_return_memory$$ 00907 $spell 00908 num 00909 ptr 00910 thread_alloc 00911 $$ 00912 00913 $section Return Memory to thread_alloc$$ 00914 00915 $index return_memory, thread_alloc$$ 00916 $index thread_alloc, return_memory$$ 00917 $index memory, available$$ 00918 $index available, memory$$ 00919 $index thread, available memory$$ 00920 00921 $head Syntax$$ 00922 $codei%thread_alloc::return_memory(%v_ptr%)%$$ 00923 00924 $head Purpose$$ 00925 If $cref/hold_memory/ta_hold_memory/$$ is false, 00926 the memory is returned to the system. 00927 Otherwise, the memory is retained by $cref thread_alloc$$ for quick future use 00928 by the thread that allocated to memory. 00929 00930 $head v_ptr$$ 00931 This argument has prototype 00932 $codei% 00933 void* %v_ptr% 00934 %$$. 00935 It must be a pointer to memory that is currently in use; i.e. 00936 obtained by a previous call to 00937 $cref/get_memory/ta_get_memory/$$ and not yet returned. 00938 00939 $head Thread$$ 00940 Either the $cref/current thread/ta_thread_num/$$ must be the same as during 00941 the corresponding call to $cref/get_memory/ta_get_memory/$$, 00942 or the current execution mode must be sequential 00943 (not $cref/parallel/ta_in_parallel/$$). 00944 00945 $head NDEBUG$$ 00946 If $code NDEBUG$$ is defined, $icode v_ptr$$ is not checked (this is faster). 00947 Otherwise, a list of in use pointers is searched to make sure 00948 that $icode v_ptr$$ is in the list. 00949 00950 $head Example$$ 00951 $cref thread_alloc.cpp$$ 00952 00953 $end 00954 */ 00955 /*! 00956 Return memory that was obtained by \c get_memory. 00957 If <code>num_threads() == 1</code>, 00958 the memory is returned to the system. 00959 Otherwise, it is retained by \c thread_alloc and available for use by 00960 \c get_memory for this thread. 00961 00962 \param v_ptr [in] 00963 Value of the pointer returned by \c get_memory and still in use. 00964 After this call, this pointer will available (and not in use). 00965 00966 \par 00967 We must either be in sequential (not parallel) execution mode, 00968 or the current thread must be the same as for the corresponding call 00969 to \c get_memory. 00970 */ 00971 static void return_memory(void* v_ptr) 00972 { size_t num_cap = capacity_info()->number; 00973 00974 block_t* node = reinterpret_cast<block_t*>(v_ptr) - 1; 00975 size_t tc_index = node->tc_index_; 00976 size_t thread = tc_index / num_cap; 00977 size_t c_index = tc_index % num_cap; 00978 size_t capacity = capacity_info()->value[c_index]; 00979 00980 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS ); 00981 CPPAD_ASSERT_KNOWN( 00982 thread == thread_num() || (! in_parallel()), 00983 "Attempt to return memory for a different thread " 00984 "while in parallel mode" 00985 ); 00986 00987 thread_alloc_info* info = thread_info(thread); 00988 # ifndef NDEBUG 00989 // remove node from inuse list 00990 void* v_node = reinterpret_cast<void*>(node); 00991 block_t* inuse_root = info->root_inuse_ + c_index; 00992 block_t* previous = inuse_root; 00993 while( (previous->next_ != 0) & (previous->next_ != v_node) ) 00994 previous = reinterpret_cast<block_t*>(previous->next_); 00995 00996 // check that v_ptr is valid 00997 if( previous->next_ != v_node ) 00998 { using std::endl; 00999 std::ostringstream oss; 01000 oss << "return_memory: attempt to return memory not in use"; 01001 oss << endl; 01002 oss << "v_ptr = " << v_ptr << endl; 01003 oss << "thread = " << thread << endl; 01004 oss << "capacity = " << capacity << endl; 01005 oss << "See CPPAD_TRACE_THREAD & CPPAD_TRACE_CAPACITY in"; 01006 oss << endl << "# include <cppad/thread_alloc.hpp>" << endl; 01007 CPPAD_ASSERT_KNOWN(false, oss.str().c_str() ); 01008 } 01009 01010 // trace option 01011 if( capacity==CPPAD_TRACE_CAPACITY && thread==CPPAD_TRACE_THREAD ) 01012 { std::cout << "return_memory: v_ptr = " << v_ptr << std::endl; } 01013 01014 // remove v_ptr from inuse list 01015 previous->next_ = node->next_; 01016 # endif 01017 // capacity bytes are removed from the inuse pool 01018 dec_inuse(capacity, thread); 01019 01020 // check for case where we just return the memory to the system 01021 if( ! set_get_hold_memory(false) ) 01022 { ::operator delete( reinterpret_cast<void*>(node) ); 01023 return; 01024 } 01025 01026 // add this node to available list for this thread and capacity 01027 block_t* available_root = info->root_available_ + c_index; 01028 node->next_ = available_root->next_; 01029 available_root->next_ = reinterpret_cast<void*>(node); 01030 01031 // capacity bytes are added to the available pool 01032 inc_available(capacity, thread); 01033 } 01034 /* ----------------------------------------------------------------------- 01035 $begin ta_free_available$$ 01036 $spell 01037 num 01038 thread_alloc 01039 $$ 01040 01041 $section Free Memory Currently Available for Quick Use by a Thread$$ 01042 $spell 01043 inuse 01044 $$ 01045 01046 $index free_available, thread_alloc$$ 01047 $index thread_alloc, free_available$$ 01048 $index free, available$$ 01049 $index available, free$$ 01050 $index thread, free memory$$ 01051 01052 $head Syntax$$ 01053 $codei%thread_alloc::free_available(%thread%)%$$ 01054 01055 $head Purpose$$ 01056 Return to the system all the memory that is currently being 01057 $cref/held/ta_hold_memory/$$ for quick use by the specified thread. 01058 01059 $subhead Extra Memory$$ 01060 In the case where $icode%thread% > 0%$$, 01061 some extra memory is used to track allocations by the specified thread. 01062 If 01063 $codei% 01064 thread_alloc::inuse(%thread%) == 0 01065 %$$ 01066 the extra memory is also returned to the system. 01067 01068 $head thread$$ 01069 This argument has prototype 01070 $codei% 01071 size_t %thread% 01072 %$$ 01073 Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, 01074 or the current execution mode must be sequential 01075 (not $cref/parallel/ta_in_parallel/$$). 01076 01077 $head Example$$ 01078 $cref thread_alloc.cpp$$ 01079 01080 $end 01081 */ 01082 /*! 01083 Return all the memory being held as available for a thread to the system. 01084 01085 \param thread [in] 01086 this thread that will no longer have any available memory after this call. 01087 This must either be the thread currently executing, or we must be 01088 in sequential (not parallel) execution mode. 01089 */ 01090 static void free_available(size_t thread) 01091 { CPPAD_ASSERT_KNOWN( 01092 thread < CPPAD_MAX_NUM_THREADS, 01093 "Attempt to free memory for a thread >= CPPAD_MAX_NUM_THREADS" 01094 ); 01095 CPPAD_ASSERT_KNOWN( 01096 thread == thread_num() || (! in_parallel()), 01097 "Attempt to free memory for a different thread " 01098 "while in parallel mode" 01099 ); 01100 01101 size_t num_cap = capacity_info()->number; 01102 if( num_cap == 0 ) 01103 return; 01104 const size_t* capacity_vec = capacity_info()->value; 01105 size_t c_index; 01106 thread_alloc_info* info = thread_info(thread); 01107 for(c_index = 0; c_index < num_cap; c_index++) 01108 { size_t capacity = capacity_vec[c_index]; 01109 block_t* available_root = info->root_available_ + c_index; 01110 void* v_ptr = available_root->next_; 01111 while( v_ptr != 0 ) 01112 { block_t* node = reinterpret_cast<block_t*>(v_ptr); 01113 void* next = node->next_; 01114 ::operator delete(v_ptr); 01115 v_ptr = next; 01116 01117 dec_available(capacity, thread); 01118 } 01119 available_root->next_ = 0; 01120 } 01121 CPPAD_ASSERT_UNKNOWN( available(thread) == 0 ); 01122 if( inuse(thread) == 0 ) 01123 { // clear the information for this thread 01124 thread_info(thread, true); 01125 } 01126 } 01127 /* ----------------------------------------------------------------------- 01128 $begin ta_hold_memory$$ 01129 $spell 01130 alloc 01131 num 01132 $$ 01133 01134 $section Control When Thread Alloc Retains Memory For Future Use$$ 01135 $index thread_alloc, hold memory$$ 01136 $index hold, thread_alloc memory$$ 01137 $index memory, thread_alloc hold$$ 01138 01139 $head Syntax$$ 01140 $codei%thread_alloc::hold_memory(%value%)%$$ 01141 01142 $head Purpose$$ 01143 It should be faster, even when $icode num_thread$$ is equal to one, 01144 for $code thread_alloc$$ to hold onto memory. 01145 Calling $icode hold_memory$$ with $icode value$$ equal to true, 01146 instructs $code thread_alloc$$ to hold onto memory, 01147 and put it in the $cref/available/ta_available/$$ pool, 01148 after each call to $cref/return_memory/ta_return_memory/$$. 01149 01150 $head value$$ 01151 If $icode value$$ is true, 01152 $code thread_alloc$$ with hold onto memory for future quick use. 01153 If it is false, future calls to $cref/return_memory/ta_return_memory/$$ 01154 will return the corresponding memory to the system. 01155 By default (when $code hold_memory$$ has not been called) 01156 $code thread_alloc$$ does not hold onto memory. 01157 01158 $head free_available$$ 01159 Memory that is being held by $code thread_alloc$$ can be returned 01160 to the system using $cref/free_available/ta_free_available/$$. 01161 01162 $end 01163 */ 01164 /*! 01165 Change the thread_alloc hold memory setting. 01166 01167 \param value [in] 01168 New value for the thread_alloc hold memory setting. 01169 */ 01170 static void hold_memory(bool value) 01171 { bool set = true; 01172 set_get_hold_memory(set, value); 01173 } 01174 01175 /* ----------------------------------------------------------------------- 01176 $begin ta_inuse$$ 01177 $spell 01178 num 01179 inuse 01180 thread_alloc 01181 $$ 01182 01183 $section Amount of Memory a Thread is Currently Using$$ 01184 01185 $index inuse, thread_alloc$$ 01186 $index thread_alloc, inuse$$ 01187 $index use, memory$$ 01188 $index thread, memory inuse$$ 01189 01190 $head Syntax$$ 01191 $icode%num_bytes% = thread_alloc::inuse(%thread%)%$$ 01192 01193 $head Purpose$$ 01194 Memory being managed by $cref thread_alloc$$ has two states, 01195 currently in use by the specified thread, 01196 and quickly available for future use by the specified thread. 01197 This function informs the program how much memory is in use. 01198 01199 $head thread$$ 01200 This argument has prototype 01201 $codei% 01202 size_t %thread% 01203 %$$ 01204 Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, 01205 or the current execution mode must be sequential 01206 (not $cref/parallel/ta_in_parallel/$$). 01207 01208 $head num_bytes$$ 01209 The return value has prototype 01210 $codei% 01211 size_t %num_bytes% 01212 %$$ 01213 It is the number of bytes currently in use by the specified thread. 01214 01215 $head Example$$ 01216 $cref thread_alloc.cpp$$ 01217 01218 $end 01219 */ 01220 /*! 01221 Determine the amount of memory that is currently inuse. 01222 01223 \param thread [in] 01224 Thread for which we are determining the amount of memory 01225 (must be < CPPAD_MAX_NUM_THREADS). 01226 Durring parallel execution, this must be the thread 01227 that is currently executing. 01228 01229 \return 01230 The amount of memory in bytes. 01231 */ 01232 static size_t inuse(size_t thread) 01233 { 01234 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); 01235 CPPAD_ASSERT_UNKNOWN( 01236 thread == thread_num() || (! in_parallel()) 01237 ); 01238 thread_alloc_info* info = thread_info(thread); 01239 return info->count_inuse_; 01240 } 01241 /* ----------------------------------------------------------------------- 01242 $begin ta_available$$ 01243 $spell 01244 num 01245 thread_alloc 01246 $$ 01247 01248 $section Amount of Memory Available for Quick Use by a Thread$$ 01249 01250 $index available, thread_alloc$$ 01251 $index thread_alloc, available$$ 01252 $index memory, available$$ 01253 $index thread, available memory$$ 01254 01255 $head Syntax$$ 01256 $icode%num_bytes% = thread_alloc::available(%thread%)%$$ 01257 01258 $head Purpose$$ 01259 Memory being managed by $cref thread_alloc$$ has two states, 01260 currently in use by the specified thread, 01261 and quickly available for future use by the specified thread. 01262 This function informs the program how much memory is available. 01263 01264 $head thread$$ 01265 This argument has prototype 01266 $codei% 01267 size_t %thread% 01268 %$$ 01269 Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$, 01270 or the current execution mode must be sequential 01271 (not $cref/parallel/ta_in_parallel/$$). 01272 01273 $head num_bytes$$ 01274 The return value has prototype 01275 $codei% 01276 size_t %num_bytes% 01277 %$$ 01278 It is the number of bytes currently available for use by the specified thread. 01279 01280 $head Example$$ 01281 $cref thread_alloc.cpp$$ 01282 01283 $end 01284 */ 01285 /*! 01286 Determine the amount of memory that is currently available for use. 01287 01288 \copydetails inuse 01289 */ 01290 static size_t available(size_t thread) 01291 { 01292 CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS); 01293 CPPAD_ASSERT_UNKNOWN( 01294 thread == thread_num() || (! in_parallel()) 01295 ); 01296 thread_alloc_info* info = thread_info(thread); 01297 return info->count_available_; 01298 } 01299 /* ----------------------------------------------------------------------- 01300 $begin ta_create_array$$ 01301 $spell 01302 inuse 01303 thread_alloc 01304 sizeof 01305 $$ 01306 01307 $section Allocate An Array and Call Default Constructor for its Elements$$ 01308 01309 $index create_array, thread_alloc$$ 01310 $index thread_alloc, create_array$$ 01311 $index array, allocate$$ 01312 $index allocate, array$$ 01313 01314 $head Syntax$$ 01315 $icode%array% = thread_alloc::create_array<%Type%>(%size_min%, %size_out%)%$$. 01316 01317 $head Purpose$$ 01318 Create a new raw array using $cref thread_alloc$$ memory allocator 01319 (works well in a multi-threading environment) 01320 and call default constructor for each element. 01321 01322 $head Type$$ 01323 The type of the elements of the array. 01324 01325 $head size_min$$ 01326 This argument has prototype 01327 $codei% 01328 size_t %size_min% 01329 %$$ 01330 This is the minimum number of elements that there can be 01331 in the resulting $icode array$$. 01332 01333 $head size_out$$ 01334 This argument has prototype 01335 $codei% 01336 size_t& %size_out% 01337 %$$ 01338 The input value of this argument does not matter. 01339 Upon return, it is the actual number of elements 01340 in $icode array$$ 01341 ($icode% size_min %<=% size_out%$$). 01342 01343 $head array$$ 01344 The return value $icode array$$ has prototype 01345 $codei% 01346 %Type%* %array% 01347 %$$ 01348 It is array with $icode size_out$$ elements. 01349 The default constructor for $icode Type$$ is used to initialize the 01350 elements of $icode array$$. 01351 Note that $cref/delete_array/ta_delete_array/$$ 01352 should be used to destroy the array when it is no longer needed. 01353 01354 $head Delta$$ 01355 The amount of memory $cref/inuse/ta_inuse/$$ by the current thread, 01356 will increase $icode delta$$ where 01357 $codei% 01358 sizeof(%Type%) * (%size_out% + 1) > %delta% >= sizeof(%Type%) * %size_out% 01359 %$$ 01360 The $cref/available/ta_available/$$ memory will decrease by $icode delta$$, 01361 (and the allocation will be faster) 01362 if a previous allocation with $icode size_min$$ between its current value 01363 and $icode size_out$$ is available. 01364 01365 $head Example$$ 01366 $cref thread_alloc.cpp$$ 01367 01368 $end 01369 */ 01370 /*! 01371 Use thread_alloc to allocate an array, then call default construtor 01372 for each element. 01373 01374 \tparam Type 01375 The type of the elements of the array. 01376 01377 \param size_min [in] 01378 The minimum number of elements in the array. 01379 01380 \param size_out [out] 01381 The actual number of elements in the array. 01382 01383 \return 01384 pointer to the first element of the array. 01385 The default constructor is used to initialize 01386 all the elements of the array. 01387 01388 \par 01389 The \c extra_ field, in the \c thread_alloc node before the return value, 01390 is set to size_out. 01391 */ 01392 template <class Type> 01393 static Type* create_array(size_t size_min, size_t& size_out) 01394 { // minimum number of bytes to allocate 01395 size_t min_bytes = size_min * sizeof(Type); 01396 // do the allocation 01397 size_t num_bytes; 01398 void* v_ptr = get_memory(min_bytes, num_bytes); 01399 // This is where the array starts 01400 Type* array = reinterpret_cast<Type*>(v_ptr); 01401 // number of Type values in the allocation 01402 size_out = num_bytes / sizeof(Type); 01403 // store this number in the extra field 01404 block_t* node = reinterpret_cast<block_t*>(v_ptr) - 1; 01405 node->extra_ = size_out; 01406 01407 // call default constructor for each element 01408 size_t i; 01409 for(i = 0; i < size_out; i++) 01410 new(array + i) Type(); 01411 01412 return array; 01413 } 01414 /* ----------------------------------------------------------------------- 01415 $begin ta_delete_array$$ 01416 $spell 01417 inuse 01418 thread_alloc 01419 sizeof 01420 deallocate 01421 $$ 01422 01423 $section Deallocate An Array and Call Destructor for its Elements$$ 01424 01425 $index delete_array, thread_alloc$$ 01426 $index thread_alloc, delete_array$$ 01427 $index array, allocate$$ 01428 $index allocate, array$$ 01429 01430 $head Syntax$$ 01431 $codei%thread_alloc::delete_array(%array%)%$$. 01432 01433 $head Purpose$$ 01434 Returns memory corresponding to an array created by 01435 (create by $cref/create_array/ta_create_array/$$) to the 01436 $cref/available/ta_available/$$ memory pool for the current thread. 01437 01438 $head Type$$ 01439 The type of the elements of the array. 01440 01441 $head array$$ 01442 The argument $icode array$$ has prototype 01443 $codei% 01444 %Type%* %array% 01445 %$$ 01446 It is a value returned by $cref/create_array/ta_create_array/$$ and not yet deleted. 01447 The $icode Type$$ destructor is called for each element in the array. 01448 01449 $head Thread$$ 01450 The $cref/current thread/ta_thread_num/$$ must be the 01451 same as when $cref/create_array/ta_create_array/$$ returned the value $icode array$$. 01452 There is an exception to this rule: 01453 when the current execution mode is sequential 01454 (not $cref/parallel/ta_in_parallel/$$) the current thread number does not matter. 01455 01456 $head Delta$$ 01457 The amount of memory $cref/inuse/ta_inuse/$$ will decrease by $icode delta$$, 01458 and the $cref/available/ta_available/$$ memory will increase by $icode delta$$, 01459 where $cref/delta/ta_create_array/Delta/$$ 01460 is the same as for the corresponding call to $code create_array$$. 01461 01462 $head Example$$ 01463 $cref thread_alloc.cpp$$ 01464 01465 $end 01466 */ 01467 /*! 01468 Return Memory Used for an Array to the Available Pool 01469 (include destructor call for each element). 01470 01471 \tparam Type 01472 The type of the elements of the array. 01473 01474 \param array [in] 01475 A value returned by \c create_array that has not yet been deleted. 01476 The \c Type destructor is used to destroy each of the elements 01477 of the array. 01478 01479 \par 01480 Durring parallel execution, the current thread must be the same 01481 as during the corresponding call to \c create_array. 01482 */ 01483 template <class Type> 01484 static void delete_array(Type* array) 01485 { // determine the number of values in the array 01486 block_t* node = reinterpret_cast<block_t*>(array) - 1; 01487 size_t size = node->extra_; 01488 01489 // call destructor for each element 01490 size_t i; 01491 for(i = 0; i < size; i++) 01492 (array + i)->~Type(); 01493 01494 // return the memory to the available pool for this thread 01495 thread_alloc::return_memory( reinterpret_cast<void*>(array) ); 01496 } 01497 /* ----------------------------------------------------------------------- 01498 $begin ta_free_all$$ 01499 $spell 01500 alloc 01501 bool 01502 inuse 01503 $$ 01504 01505 $section Free All Memory That Was Allocated for Use by thread_alloc$$ 01506 01507 $index free, all thread_alloc$$ 01508 $index thread_alloc, free all$$ 01509 01510 $head Syntax$$ 01511 $icode%ok% = thread_alloc::free_all()%$$. 01512 01513 $head Purpose$$ 01514 Returns all memory that was used by $code thread_alloc$$ to the system. 01515 01516 $head ok$$ 01517 The return value $icode ok$$ has prototype 01518 $codei% 01519 bool %ok% 01520 %$$ 01521 Its value will be $code true$$ if all the memory can be freed. 01522 This requires that for all $icode thread$$ indices, there is no memory 01523 $cref/inuse/ta_inuse/$$; i.e., 01524 $codei% 01525 0 == thread_alloc::inuse(%thread%) 01526 %$$ 01527 Otherwise, the return value will be false. 01528 01529 $head Restrictions$$ 01530 This function cannot be called while in parallel mode. 01531 01532 $head Example$$ 01533 $cref thread_alloc.cpp$$ 01534 $end 01535 */ 01536 /*! 01537 Return to the system all thread_alloc memory that is not currently inuse. 01538 01539 \return 01540 If no \c thread_alloc memory is currently inuse, 01541 all memory is returned to the system and the return value is true. 01542 Otherwise the return value is false. 01543 */ 01544 static bool free_all(void) 01545 { CPPAD_ASSERT_KNOWN( 01546 ! in_parallel(), 01547 "free_all cannot be used while in parallel execution" 01548 ); 01549 bool ok = true; 01550 size_t thread = CPPAD_MAX_NUM_THREADS; 01551 while(thread--) 01552 { ok &= inuse(thread) == 0; 01553 free_available(thread); 01554 } 01555 return ok; 01556 } 01557 }; 01558 01559 01560 /*! \} */ 01561 CPPAD_END_NAMESPACE 01562 01563 // preprocessor symbols local to this file 01564 # undef CPPAD_MAX_NUM_CAPACITY 01565 # undef CPPAD_MIN_DOUBLE_CAPACITY 01566 # undef CPPAD_TRACE_CAPACITY 01567 # undef CPPAD_TRACE_THREAD 01568 # endif