source: trunk/cppad/thread_alloc.hpp @ 2910

Last change on this file since 2910 was 2910, checked in by bradbell, 7 years ago

Remove CPPAD_BEGIN_NAMESPACE, CPPAD_END_NAMESPACE, and instead use

namespace CppAD { BEGIN_CPPAD_NAMESPACE
}
END_CPPAD_NAMESPACE

becasue doxygen 1.8.3 gets confused when using a macro for this purpose
(begining and ending the CppAD namespace without indenting code).

  • Property svn:keywords set to Id
File size: 44.0 KB
Line 
1/* $Id: thread_alloc.hpp 2910 2013-10-07 13:27:58Z bradbell $ */
2# ifndef CPPAD_THREAD_ALLOC_INCLUDED
3# define CPPAD_THREAD_ALLOC_INCLUDED
4
5/* --------------------------------------------------------------------------
6CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-13 Bradley M. Bell
7
8CppAD is distributed under multiple licenses. This distribution is under
9the terms of the
10                    Eclipse Public License Version 1.0.
11
12A copy of this license is included in the COPYING file of this distribution.
13Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
14-------------------------------------------------------------------------- */
15
16# include <sstream>
17# include <limits>
18# include <memory>
19
20
21# ifdef _MSC_VER
22// Supress warning that Microsoft compiler changed its behavior and is now
23// doing the correct thing at the statement:
24//                      new(array + i) Type();
25# pragma warning(disable:4345)
26# endif
27
28# include <cppad/local/cppad_assert.hpp>
29# include <cppad/local/define.hpp>
30namespace CppAD { // BEGIN_CPPAD_NAMESPACE
31/*!
32\defgroup thread_alloc_hpp thread_alloc.hpp
33\{
34\file thread_alloc.hpp
35File used to define the CppAD multi-threading allocaor class
36*/
37
38/*!
39\def CPPAD_MAX_NUM_CAPACITY
40Maximum number of different capacities the allocator will attempt.
41This must be larger than the log base two of numeric_limit<size_t>::max().
42*/
43# define CPPAD_MAX_NUM_CAPACITY 100
44
45/*!
46\def CPPAD_MIN_DOUBLE_CAPACITY
47Minimum number of double values that will fit in an allocation.
48*/
49# define CPPAD_MIN_DOUBLE_CAPACITY 16
50
51/*!
52\def CPPAD_TRACE_CAPACITY
53If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory
54that correspond to this capacity and thread CPPAD_TRACE_THEAD.
55(Note that if CPPAD_TRACE_CAPACITY is zero, or any other value not in the list
56of capacities, no tracing will be done.)
57*/
58# define CPPAD_TRACE_CAPACITY 0
59
60/*!
61\def CPPAD_TRACE_THREAD
62If NDEBUG is not defined, print all calls to \c get_memory and \c return_memory
63that correspond to this thead and capacity CPPAD_TRACE_CAPACITY.
64*/
65# define CPPAD_TRACE_THREAD 0
66
67/*
68Note that Section 3.6.2 of ISO/IEC 14882:1998(E) states: "The storage for
69objects with static storage duration (3.7.1) shall be zero-initialized
70(8.5) before any other initialization takes place."
71*/
72
73/*!
74Capacity vector for memory allocation block sizes.
75
76Only one of these objects should be created and used as a
77static variable inside of the \c thread_alloc::capacity_info function.
78*/
79
80/*!
81Allocator class that works well with an multi-threading environment.
82*/
83class thread_alloc{
84// ============================================================================
85private:
86       
87        class capacity_t {
88        public:
89                /// number of capacity values actually used
90                size_t number;
91                /// the different capacity values
92                size_t value[CPPAD_MAX_NUM_CAPACITY];
93                /// ctor
94                capacity_t(void)
95                {       // Cannot figure out how to call thread_alloc::in_parallel here.
96                        // CPPAD_ASSERT_UNKNOWN(
97                        //      ! thread_alloc::in_parallel() , "thread_alloc: "
98                        //      "parallel mode and parallel_setup not yet called."
99                        // );
100                        number           = 0;
101                        size_t capacity  = CPPAD_MIN_DOUBLE_CAPACITY * sizeof(double);
102                        while( capacity < std::numeric_limits<size_t>::max() / 2 )
103                        {       CPPAD_ASSERT_UNKNOWN( number < CPPAD_MAX_NUM_CAPACITY );
104                                value[number++] = capacity;
105                                // next capactiy is 3/2 times the current one
106                                capacity        = 3 * ( (capacity + 1) / 2 );
107                        }               
108                        CPPAD_ASSERT_UNKNOWN( number > 0 );
109                }
110        };
111
112        class block_t {
113        public:
114                /// extra information (currently used by create and delete array)
115                size_t             extra_;
116                /// an index that uniquely idenfifies both thread and capacity
117                size_t             tc_index_;
118                /// pointer to the next memory allocation with the the same tc_index_
119                void*              next_;
120                // -----------------------------------------------------------------
121                /// make default constructor private. It is only used by constructor
122                /// for `root arrays below.
123                block_t(void) : extra_(0), tc_index_(0), next_(CPPAD_NULL) 
124                { }
125        };
126
127        // ---------------------------------------------------------------------
128        /// Vector of fixed capacity values for this allocator
129        static const capacity_t* capacity_info(void)
130        {       CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
131                static const capacity_t capacity;
132                return &capacity;
133        }
134        // ---------------------------------------------------------------------
135        /// Structure of information for each thread
136        struct thread_alloc_info {
137                /// count of available bytes for this thread
138                size_t  count_inuse_;
139                /// count of inuse bytes for this thread
140                size_t  count_available_;
141                /// root of available list for this thread and each capacity
142                block_t root_available_[CPPAD_MAX_NUM_CAPACITY];
143                /// root of inuse list for this thread and each capacity
144                /// If NDEBUG is true, this memory is not used, but it still
145                /// helps separate this structure from one for the next thread.
146                block_t root_inuse_[CPPAD_MAX_NUM_CAPACITY];
147        };
148        // ---------------------------------------------------------------------
149        /*!
150        Set and Get hold available memory flag.
151
152        \param set [in]
153        if true, the value returned by this return is changed.
154
155        \param new_value [in]
156        if \a set is true, this is the new value returned by this routine.
157        Otherwise, \c new_value is ignored.
158
159        \return
160        the current setting for this routine (which is initially false).
161        */
162        static bool set_get_hold_memory(bool set, bool new_value = false)
163        {       static bool value = false;
164                if( set )
165                        value = new_value;
166                return value;
167        }
168        // ---------------------------------------------------------------------
169        /*!
170        Get pointer to the information for this thread.
171
172        \param thread [in]
173        Is the thread number for this information pointer.
174
175        \param clear
176        If \a clear is true, then the information pointer for this thread
177        is deleted and the \c CPPAD_NULL pointer is returned.
178        There must be no memory currently in either the inuse or avaialble
179        lists when this routine is called.
180
181        \return
182        is the current informaiton pointer for this thread.
183        If \a clear is false, and the current pointer is CPPAD_NULL,
184        a new infromation record is allocated and its pointer returned.
185        In this case, if \c info is the retured pointer,
186        <code>info->count_inuse == 0</code> and
187        <code>info->count_available == 0</code>.
188        In addition,
189        for <code>c = 0 , ... , CPPAD_MAX_NUM_CAPACITY-1</code>
190        <code>info->root_inuse_[c].next_ == CPPAD_NULL</code> and
191        <code>info->root_available_[c].next_ == CPPAD_NULL</code>.
192        */
193        static thread_alloc_info* thread_info(
194                size_t             thread          ,
195                bool               clear = false   )
196        {       static thread_alloc_info* all_info[CPPAD_MAX_NUM_THREADS];
197                static thread_alloc_info  zero_info;
198
199                CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
200
201                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS );
202
203                thread_alloc_info* info = all_info[thread];
204                if( clear )
205                {       if( info != CPPAD_NULL )
206                        {
207# ifndef NDEBUG
208                                CPPAD_ASSERT_UNKNOWN(
209                                        info->count_inuse_     == 0 &&
210                                        info->count_available_ == 0
211                                );
212                                for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++)
213                                {       CPPAD_ASSERT_UNKNOWN(
214                                                info->root_inuse_[c].next_     == CPPAD_NULL &&
215                                                info->root_available_[c].next_ == CPPAD_NULL
216                                        );
217                                }
218# endif
219                                if( thread != 0 )
220                                        ::operator delete( reinterpret_cast<void*>(info) );
221                                info             = CPPAD_NULL;
222                                all_info[thread] = info;
223                        }
224                }
225                else if( info == CPPAD_NULL )
226                {       if( thread == 0 )
227                                info = &zero_info;
228                        else
229                        {       size_t size = sizeof(thread_alloc_info);
230                                void* v_ptr = ::operator new(size);
231                                info        = reinterpret_cast<thread_alloc_info*>(v_ptr);
232                        }
233                        all_info[thread] = info;
234
235                        // initialize the information record
236                        for(size_t c = 0; c < CPPAD_MAX_NUM_CAPACITY; c++)
237                        {       info->root_inuse_[c].next_       = CPPAD_NULL;
238                                info->root_available_[c].next_   = CPPAD_NULL;
239                        }
240                        info->count_inuse_     = 0;
241                        info->count_available_ = 0;
242                }
243                return info;
244        }
245        // -----------------------------------------------------------------------
246        /*!
247        Increase the number of bytes of memory that are currently in use; i.e.,
248        that been obtained with \c get_memory and not yet returned.
249
250        \param inc [in]
251        amount to increase memory in use.
252
253        \param thread [in]
254        Thread for which we are increasing the number of bytes in use
255        (must be less than \c num_threads).
256        Durring parallel execution, this must be the thread
257        that is currently executing.
258        */
259        static void inc_inuse(size_t inc, size_t thread)
260        {       
261                CPPAD_ASSERT_UNKNOWN( thread < num_threads() );
262                CPPAD_ASSERT_UNKNOWN( 
263                        thread == thread_num() || (! in_parallel()) 
264                );
265                thread_alloc_info* info = thread_info(thread);
266               
267                // do the addition
268                size_t result = info->count_inuse_ + inc;
269                CPPAD_ASSERT_UNKNOWN( result >= info->count_inuse_ );
270
271                info->count_inuse_ = result;
272        }
273        // -----------------------------------------------------------------------
274        /*!
275        Increase the number of bytes of memory that are currently avaialble; i.e.,
276        have been obtained obtained from the system and are being held future use.
277
278        \copydetails inc_inuse
279        */
280        static void inc_available(size_t inc, size_t thread)
281        {       
282                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);
283                CPPAD_ASSERT_UNKNOWN( 
284                        thread == thread_num() || (! in_parallel()) 
285                );
286                thread_alloc_info* info = thread_info(thread);
287                // do the addition
288                size_t result = info->count_available_ + inc;
289                CPPAD_ASSERT_UNKNOWN( result >= info->count_available_ );
290
291                info->count_available_ = result;
292        }
293        // -----------------------------------------------------------------------
294        /*!
295        Decrease the number of bytes of memory that are currently in use; i.e.,
296        that been obtained with \c get_memory and not yet returned.
297
298        \param dec [in]
299        amount to decrease number of bytes in use.
300
301        \param thread [in]
302        Thread for which we are decreasing the number of bytes in use
303        (must be less than \c num_threads).
304        Durring parallel execution, this must be the thread
305        that is currently executing.
306        */
307        static void dec_inuse(size_t dec, size_t thread)
308        {       
309                CPPAD_ASSERT_UNKNOWN(
310                        thread < num_threads() || (! in_parallel())
311                );
312                CPPAD_ASSERT_UNKNOWN( 
313                        thread == thread_num() || (! in_parallel()) 
314                );
315                thread_alloc_info* info = thread_info(thread);
316
317                // do the subtraction
318                CPPAD_ASSERT_UNKNOWN( info->count_inuse_ >= dec );
319                info->count_inuse_ = info->count_inuse_ - dec;
320        }
321        // -----------------------------------------------------------------------
322        /*!
323        Decrease the number of bytes of memory that are currently avaialble; i.e.,
324        have been obtained obtained from the system and are being held future use.
325
326        \copydetails dec_inuse
327        */
328        static void dec_available(size_t dec, size_t thread)
329        {       
330                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);
331                CPPAD_ASSERT_UNKNOWN( 
332                        thread == thread_num() || (! in_parallel()) 
333                );
334                thread_alloc_info* info = thread_info(thread);
335                // do the subtraction
336                CPPAD_ASSERT_UNKNOWN( info->count_available_ >= dec );
337                info->count_available_ =  info->count_available_ - dec;
338        }
339
340        // ----------------------------------------------------------------------
341        /*!
342        Set and get the number of threads that are sharing memory.
343
344        \param number_new
345        If \c number is zero, we are only retreiving the current maximum
346        number of threads. Otherwise, we are setting and retreiving
347        maximum number of threads.
348
349        \return
350        the number of threads that are sharing memory.
351        If \c number_new is non-zero, the return value is equal to
352        \c number_new.
353        */
354        static size_t set_get_num_threads(size_t number_new)
355        {       static size_t number_user = 1;
356
357                CPPAD_ASSERT_UNKNOWN( number_new <= CPPAD_MAX_NUM_THREADS );
358                CPPAD_ASSERT_UNKNOWN( ! in_parallel() || (number_new == 0) );
359
360                // case where we are changing the number of threads
361                if( number_new != 0 )
362                        number_user = number_new;
363
364                return number_user;
365        }
366        /*!
367        Set and call the routine that determine if we are in parallel
368        execution mode.
369
370        \return
371        value retuned by most recent setting for \a parallel_new.
372        If \a set is true,
373        or the most recent setting is \c CPPAD_NULL (its initial value),
374        the return value is false.
375        Otherwise the function corresponding to the most recent setting
376        is called and its value returned by \c set_get_in_parallel.
377
378        \param parallel_new [in]
379        If \a set is false, \a parallel_new it is not used.
380        Otherwise, the current value of \c parallel_new becomes the
381        most recent setting for in_parallel.
382
383        \param set
384        If \a set is true, then \a parallel_new is becomes the most
385        recent setting for this \c set_get_in_parallel.
386        */
387        static bool set_get_in_parallel(
388                bool (*parallel_new)(void) ,
389                bool set = false           )
390        {       static bool (*parallel_user)(void) = CPPAD_NULL;
391
392                if( set )
393                {       parallel_user = parallel_new;
394                        return false;
395                }
396
397                if( parallel_user == CPPAD_NULL )
398                        return false;
399
400                return parallel_user();
401        }
402        /*!
403        Set and call the routine that determine the current thread number.
404
405        \return
406        returns value for the most recent setting for \a thread_num_new.
407        If \a set is true,
408        or the most recent setting is \c CPPAD_NULL (its initial value),
409        the return value is zero.
410        Otherwise the routine corresponding to the most recent setting
411        is called and its value returned by \c set_get_thread_num.
412
413        \param thread_num_new [in]
414        If \a set is false, \a thread_num_new it is not used.
415        Otherwise, the current value of \c thread_num_new becomes the
416        most recent setting for thread_num.
417
418        \param set
419        If \a set is true, then \a thread_num_new is becomes the most
420        recent setting for this \c set_get_thread_num.
421        */
422        static size_t set_get_thread_num(
423                size_t (*thread_num_new)(void)  ,
424                bool set = false                )
425        {       static size_t (*thread_num_user)(void) = CPPAD_NULL;
426
427                if( set )
428                {       thread_num_user = thread_num_new;
429                        return 0;
430                }
431
432                if( thread_num_user == CPPAD_NULL )
433                        return 0;
434
435                size_t thread = thread_num_user();
436                CPPAD_ASSERT_KNOWN(
437                        thread < set_get_num_threads(0) ,
438                        "parallel_setup: thread_num() >= num_threads"
439                );
440                return thread;
441        }
442// ============================================================================
443public:
444/*
445$begin ta_parallel_setup$$
446$spell
447        alloc
448        num
449        bool
450$$
451$section Setup thread_alloc For Use in Multi-Threading Environment$$
452
453$index setup, thread_alloc$$
454$index thread_alloc, setup$$
455$index parallel, setup$$
456$index setup, parallel$$
457
458$index num_threads$$
459$index in_parallel$$
460$index thread_num$$
461
462$index multi-threading, initialize$$
463$index initialize, multi-threading$$
464
465$head Syntax$$
466$codei%thread_alloc::parallel_setup(%num_threads%, %in_parallel%, %thread_num%)
467%$$
468
469$head Purpose$$
470By default there is only one thread and all execution is in sequential mode,
471i.e., multiple threads are not sharing the same memory; i.e.
472not in parallel mode.
473
474$head Speed$$
475It should be faster, even when $icode num_thread$$ is equal to one,
476for $code thread_alloc$$ to hold onto memory.
477This can be accomplished using the function call
478$codei%
479        thread_alloc::hold_memory(true)
480%$$
481see $cref/hold_memory/ta_hold_memory/$$.
482
483$head num_threads$$
484This argument has prototype
485$codei%
486        size_t %num_threads%
487%$$
488and must be greater than zero.
489It specifies the number of threads that are sharing memory.
490The case $icode%num_threads% == 1%$$ is a special case that is
491used to terminate a multi-threading environment.
492
493$head in_parallel$$
494This function has prototype
495$codei%
496        bool %in_parallel%(void)
497%$$
498It must return $code true$$ if there is more than one thread
499currently executing.
500Otherwise it can return false.
501$pre
502
503$$
504In the special case where $icode%num_threads% == 1%$$,
505the routine $icode in_parallel$$ is not used.
506
507$head thread_num$$
508This function has prototype
509$codei%
510        size_t %thread_num%(void)
511%$$
512It must return a thread number that uniquely identifies the
513currently executing thread.
514Furthermore
515$codei%
516        0 <= %thread_num%() < %num_threads%
517%$$.
518In the special case where $icode%num_threads% == 1%$$,
519the routine $icode thread_num$$ is not used.
520$pre
521
522$$
523Note that this function is called by other routines so,
524as soon as a new thread is executing,
525one must be certain that $icode thread_num()$$ will
526work for that thread.
527
528$head Restrictions$$
529The function $code parallel_setup$$ must be called before
530the program enters $cref/parallel/ta_in_parallel/$$ execution mode.
531In addition, this function cannot be called while in parallel mode.
532
533$head Example$$
534The files
535$cref simple_ad_openmp.cpp$$,
536$cref simple_ad_bthread.cpp$$, and
537$cref simple_ad_pthread.cpp$$,
538contain examples and tests that use this function.   
539
540$end
541*/
542        /*!
543        Set thread_alloc up for parallel mode usage.
544
545        \param num_threads [in]
546        Is the number of thread that may be executing at the same time.
547
548        \param in_parallel [in]
549        Is the routine that determines if we are in parallel mode or not.
550
551        \param thread_num [in]
552        Is the routine that determines the current thread number
553        (between zero and num_threads minus one).
554        */
555        static void parallel_setup(
556                size_t num_threads         ,
557                bool (*in_parallel)(void)  ,
558                size_t (*thread_num)(void) )
559        {
560                // Special case where we go back to single thread mode right away
561                // (previous settings may no longer be valid)
562                if( num_threads == 1 )
563                {       bool set = true;
564                        set_get_num_threads(num_threads);
565                        set_get_in_parallel(CPPAD_NULL, set);
566                        set_get_thread_num(CPPAD_NULL, set);
567                        return;
568                }
569
570                CPPAD_ASSERT_KNOWN( 
571                        num_threads <= CPPAD_MAX_NUM_THREADS ,
572                        "parallel_setup: num_threads is too large"
573                );
574                CPPAD_ASSERT_KNOWN( 
575                        num_threads != 0 ,
576                        "parallel_setup: num_threads == zero"
577                );
578                CPPAD_ASSERT_KNOWN( 
579                        in_parallel != CPPAD_NULL ,
580                        "parallel_setup: num_threads != 1 and in_parallel == CPPAD_NULL"
581                );
582                CPPAD_ASSERT_KNOWN( 
583                        thread_num != CPPAD_NULL ,
584                        "parallel_setup: num_threads != 1 and thread_num == CPPAD_NULL"
585                );
586
587                // Make sure that constructors for all static variables in this file
588                // are called in sequential mode.       
589                for(size_t thread = 0; thread < num_threads; thread++)
590                        thread_info(thread);
591                capacity_info();
592                size_t cap_bytes;
593                void* v_ptr = get_memory(0, cap_bytes);
594
595                // free memory allocated by call to get_memory above
596                return_memory(v_ptr);
597                free_available( set_get_thread_num(CPPAD_NULL) );
598
599                // delay this so thread_num() call above is in previous mode
600                // (current setings may not yet be valid)
601                if( num_threads > 1 )
602                {       bool set = true;
603                        set_get_num_threads(num_threads);
604                        set_get_in_parallel(in_parallel, set);
605                        set_get_thread_num(thread_num, set);
606                }
607        }
608/*
609$begin ta_num_threads$$
610$spell
611        inv
612        CppAD
613        num
614        alloc
615$$
616$section Get Number of Threads$$
617
618$index num_threads, thread_alloc$$
619$index thread_alloc, num_threads$$
620$index threads, number of$$
621
622$head Syntax$$
623$icode%number% = thread_alloc::num_threads()%$$
624
625$head Purpose$$
626Determine the number of threads as set during $cref/parallel_setup/ta_parallel_setup/$$.
627
628$head number$$
629The return value $icode number$$ has prototype
630$codei%
631        size_t %number%
632%$$
633and is equal to the value of
634$cref/num_threads/ta_parallel_setup/num_threads/$$
635in the previous call to $icode parallel_setup$$.
636If there was no such previous call, the value one is returned.
637
638$head Example$$
639The example and test $cref thread_alloc.cpp$$ uses this routine.
640
641$end
642*/
643        /*!
644        Get the current number of threads that thread_alloc can use.
645        */
646        static size_t num_threads(void)
647        {       return set_get_num_threads(0); }
648/* -----------------------------------------------------------------------
649$begin ta_in_parallel$$
650
651$section Is The Current Execution in Parallel Mode$$
652$spell
653        thread_alloc
654        bool
655$$
656
657$index in_parallel, thread_alloc$$
658$index thread_alloc, in_parallel$$
659$index parallel, execution$$
660$index execution, parallel$$
661$index sequential, execution$$
662
663$head Syntax$$
664$icode%flag% = thread_alloc::in_parallel()%$$
665
666$head Purpose$$
667Some of the $cref thread_alloc$$ allocation routines have different
668specifications for parallel (not sequential) execution mode.
669This routine enables you to determine if the current execution mode
670is sequential or parallel.
671
672$head flag$$
673The return value has prototype
674$codei%
675        bool %flag%
676%$$
677It is true if the current execution is in parallel mode
678(possibly multi-threaded) and false otherwise (sequential mode).
679
680$head Example$$
681$cref thread_alloc.cpp$$
682
683$end
684*/
685        /// Are we in a parallel execution state; i.e., is it possible that
686        /// other threads are currently executing.
687        static bool in_parallel(void)
688        {       return set_get_in_parallel(0); }
689/* -----------------------------------------------------------------------
690$begin ta_thread_num$$
691$spell
692        CppAD
693        num
694        thread_alloc
695        cppad.hpp
696$$
697
698$section Get the Current Thread Number$$
699
700$index thread_num, thread_alloc$$
701$index thread_alloc, thread_num$$
702$index thread, current$$
703$index current, thread$$
704
705$head Syntax$$
706$icode%thread% = thread_alloc::thread_num()%$$
707
708$head Purpose$$
709Some of the $cref thread_alloc$$ allocation routines have a thread number.
710This routine enables you to determine the current thread.
711
712$head thread$$
713The return value $icode thread$$ has prototype
714$codei%
715        size_t %thread%
716%$$
717and is the currently executing thread number.
718If $code _OPENMP$$ is not defined, $icode thread$$ is zero.
719
720$head Example$$
721$cref thread_alloc.cpp$$
722
723$end
724*/
725        /// Get current thread number
726        static size_t thread_num(void)
727        {       return set_get_thread_num(CPPAD_NULL); }
728/* -----------------------------------------------------------------------
729$begin ta_get_memory$$
730$spell
731        std
732        num
733        ptr
734        thread_alloc
735$$
736
737$section Get At Least A Specified Amount of Memory$$
738
739$index thread_num, thread_alloc$$
740$index thread_alloc, thread_num$$
741$index memory, allocate$$
742$index allocate, memory$$
743
744$head Syntax$$
745$icode%v_ptr% = thread_alloc::get_memory(%min_bytes%, %cap_bytes%)%$$
746
747$head Purpose$$
748Use $cref thread_alloc$$ to obtain a minimum number of bytes of memory
749(for use by the $cref/current thread/ta_thread_num/$$).
750
751$head min_bytes$$
752This argument has prototype
753$codei%
754        size_t %min_bytes%
755%$$
756It specifies the minimum number of bytes to allocate.
757This value must be less than
758$codep
759        std::numeric_limits<size_t>::max() / 2
760$$
761
762$head cap_bytes$$
763This argument has prototype
764$codei%
765        size_t& %cap_bytes%
766%$$
767It's input value does not matter.
768Upon return, it is the actual number of bytes (capacity)
769that have been allocated for use,
770$codei%
771        %min_bytes% <= %cap_bytes%
772%$$
773
774$head v_ptr$$
775The return value $icode v_ptr$$ has prototype
776$codei%
777        void* %v_ptr%
778%$$
779It is the location where the $icode cap_bytes$$ of memory
780that have been allocated for use begins.
781
782$head Allocation Speed$$
783This allocation should be faster if the following conditions hold:
784$list number$$
785The memory allocated by a previous call to $code get_memory$$
786is currently available for use.
787$lnext
788The current $icode min_bytes$$ is between
789the previous $icode min_bytes$$ and previous $icode cap_bytes$$.
790$lend
791
792$head Example$$
793$cref thread_alloc.cpp$$
794
795$end
796*/
797        /*!
798        Use thread_alloc to get a specified amount of memory.
799
800        If the memory allocated by a previous call to \c get_memory is now
801        avaialable, and \c min_bytes is between its previous value
802        and the previous \c cap_bytes, this memory allocation will have
803        optimal speed. Otherwise, the memory allocation is more complicated and
804        may have to wait for other threads to complete an allocation.
805
806        \param min_bytes [in]
807        The minimum number of bytes of memory to be obtained for use.
808
809        \param cap_bytes [out]
810        The actual number of bytes of memory obtained for use.
811
812        \return
813        pointer to the beginning of the memory allocated for use.
814        */
815        static void* get_memory(size_t min_bytes, size_t& cap_bytes)
816        {       // see first_trace below       
817                CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
818
819                // check that number of requested bytes is not to large
820                CPPAD_ASSERT_KNOWN(
821                        min_bytes < std::numeric_limits<size_t>::max() / 2 ,
822                        "get_memory(min_bytes, cap_bytes): min_bytes is too large"
823                );
824
825                size_t num_cap = capacity_info()->number;
826                using std::cout;
827                using std::endl;
828
829                // determine the capacity for this request
830                size_t c_index   = 0;
831                const size_t* capacity_vec = capacity_info()->value;
832                while( capacity_vec[c_index] < min_bytes )
833                {       ++c_index;     
834                        CPPAD_ASSERT_UNKNOWN(c_index < num_cap );
835                }
836                cap_bytes = capacity_vec[c_index];
837
838                // determine the thread, capacity, and info for this thread
839                size_t thread            = thread_num();
840                size_t tc_index          = thread * num_cap + c_index;
841                thread_alloc_info* info  = thread_info(thread);
842
843# ifndef NDEBUG
844                // trace allocation
845                static bool first_trace = true;
846                if(     cap_bytes == CPPAD_TRACE_CAPACITY && 
847                     thread    ==  CPPAD_TRACE_THREAD  && first_trace )
848                {       cout << endl;   
849                        cout << "thread_alloc: Trace for Thread = " << thread;
850                        cout << " and capacity = " << cap_bytes << endl;
851                        if( first_trace )
852                                first_trace = false;
853                }
854
855                // Root nodes for both lists. Note these are different for different
856                // threads because tc_index is different for different threads.
857                block_t* inuse_root     = info->root_inuse_ + c_index;
858# endif
859                block_t* available_root = info->root_available_ + c_index;
860
861                // check if we already have a node we can use
862                void* v_node              = available_root->next_;
863                block_t* node             = reinterpret_cast<block_t*>(v_node);
864                if( node != CPPAD_NULL )
865                {       CPPAD_ASSERT_UNKNOWN( node->tc_index_ == tc_index );
866
867                        // remove node from available list
868                        available_root->next_ = node->next_;
869
870                        // return value for get_memory
871                        void* v_ptr = reinterpret_cast<void*>(node + 1);
872# ifndef NDEBUG
873                        // add node to inuse list
874                        node->next_           = inuse_root->next_;
875                        inuse_root->next_     = v_node;
876
877                        // trace allocation
878                        if(     cap_bytes == CPPAD_TRACE_CAPACITY && 
879                             thread    ==  CPPAD_TRACE_THREAD   )
880                        {       cout << "get_memory:    v_ptr = " << v_ptr << endl; } 
881# endif
882
883                        // adjust counts
884                        inc_inuse(cap_bytes, thread);
885                        dec_available(cap_bytes, thread);
886
887                        // return pointer to memory, do not inclue thread_alloc information
888                        return v_ptr;
889                }
890
891                // Create a new node with thread_alloc information at front.
892                // This uses the system allocator, which is thread safe, but slower,
893                // because the thread might wait for a lock on the allocator.
894                v_node          = ::operator new(sizeof(block_t) + cap_bytes);
895                node            = reinterpret_cast<block_t*>(v_node);
896                node->tc_index_ = tc_index;
897                void* v_ptr     = reinterpret_cast<void*>(node + 1);
898
899# ifndef NDEBUG
900                // add node to inuse list
901                node->next_       = inuse_root->next_;
902                inuse_root->next_ = v_node;
903
904                // trace allocation
905                if( cap_bytes == CPPAD_TRACE_CAPACITY && 
906                    thread    == CPPAD_TRACE_THREAD    )
907                {       cout << "get_memory:    v_ptr = " << v_ptr << endl; }
908# endif
909
910                // adjust counts
911                inc_inuse(cap_bytes, thread);
912
913                return v_ptr;
914        }
915
916/* -----------------------------------------------------------------------
917$begin ta_return_memory$$
918$spell
919        num
920        ptr
921        thread_alloc
922$$
923
924$section Return Memory to thread_alloc$$
925
926$index return_memory, thread_alloc$$
927$index thread_alloc, return_memory$$
928$index memory, available$$
929$index available, memory$$
930$index thread, available memory$$
931
932$head Syntax$$
933$codei%thread_alloc::return_memory(%v_ptr%)%$$
934
935$head Purpose$$
936If $cref/hold_memory/ta_hold_memory/$$ is false,
937the memory is returned to the system.
938Otherwise, the memory is retained by $cref thread_alloc$$ for quick future use
939by the thread that allocated to memory.
940
941$head v_ptr$$
942This argument has prototype
943$codei%
944        void* %v_ptr%
945%$$.
946It must be a pointer to memory that is currently in use; i.e.
947obtained by a previous call to
948$cref/get_memory/ta_get_memory/$$ and not yet returned.
949
950$head Thread$$
951Either the $cref/current thread/ta_thread_num/$$ must be the same as during
952the corresponding call to $cref/get_memory/ta_get_memory/$$,
953or the current execution mode must be sequential
954(not $cref/parallel/ta_in_parallel/$$).
955
956$head NDEBUG$$
957If $code NDEBUG$$ is defined, $icode v_ptr$$ is not checked (this is faster).
958Otherwise, a list of in use pointers is searched to make sure
959that $icode v_ptr$$ is in the list.
960
961$head Example$$
962$cref thread_alloc.cpp$$
963
964$end
965*/
966        /*!
967        Return memory that was obtained by \c get_memory.
968        If  <code>num_threads() == 1</code>,
969        the memory is returned to the system.
970        Otherwise, it is retained by \c thread_alloc and available for use by
971        \c get_memory for this thread.
972
973        \param v_ptr [in]
974        Value of the pointer returned by \c get_memory and still in use.
975        After this call, this pointer will available (and not in use).
976
977        \par
978        We must either be in sequential (not parallel) execution mode,
979        or the current thread must be the same as for the corresponding call
980        to \c get_memory.
981        */
982        static void return_memory(void* v_ptr)
983        {       size_t num_cap   = capacity_info()->number;
984
985                block_t* node    = reinterpret_cast<block_t*>(v_ptr) - 1;
986                size_t tc_index  = node->tc_index_;
987                size_t thread    = tc_index / num_cap;
988                size_t c_index   = tc_index % num_cap;
989                size_t capacity  = capacity_info()->value[c_index];
990
991                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS );
992                CPPAD_ASSERT_KNOWN( 
993                        thread == thread_num() || (! in_parallel()),
994                        "Attempt to return memory for a different thread "
995                        "while in parallel mode"
996                );
997
998                thread_alloc_info* info = thread_info(thread);
999# ifndef NDEBUG
1000                // remove node from inuse list
1001                void* v_node         = reinterpret_cast<void*>(node);
1002                block_t* inuse_root  = info->root_inuse_ + c_index;
1003                block_t* previous    = inuse_root;
1004                while( (previous->next_ != CPPAD_NULL) & (previous->next_ != v_node) )
1005                        previous = reinterpret_cast<block_t*>(previous->next_); 
1006
1007                // check that v_ptr is valid
1008                if( previous->next_ != v_node )
1009                {       using std::endl;
1010                        std::ostringstream oss;
1011                        oss << "return_memory: attempt to return memory not in use";
1012                        oss << endl;
1013                        oss << "v_ptr    = " << v_ptr    << endl;   
1014                        oss << "thread   = " << thread   << endl;   
1015                        oss << "capacity = " << capacity << endl;   
1016                        oss << "See CPPAD_TRACE_THREAD & CPPAD_TRACE_CAPACITY in";
1017                        oss << endl << "# include <cppad/thread_alloc.hpp>" << endl;
1018                        CPPAD_ASSERT_KNOWN(false, oss.str().c_str()     ); 
1019                }
1020
1021                // trace option
1022                if( capacity==CPPAD_TRACE_CAPACITY && thread==CPPAD_TRACE_THREAD )
1023                {       std::cout << "return_memory: v_ptr = " << v_ptr << std::endl; }
1024
1025                // remove v_ptr from inuse list
1026                previous->next_  = node->next_;
1027# endif
1028                // capacity bytes are removed from the inuse pool
1029                dec_inuse(capacity, thread);
1030
1031                // check for case where we just return the memory to the system
1032                if( ! set_get_hold_memory(false) )
1033                {       ::operator delete( reinterpret_cast<void*>(node) );
1034                        return;
1035                }
1036
1037                // add this node to available list for this thread and capacity
1038                block_t* available_root = info->root_available_ + c_index;
1039                node->next_             = available_root->next_;
1040                available_root->next_   = reinterpret_cast<void*>(node);
1041
1042                // capacity bytes are added to the available pool
1043                inc_available(capacity, thread);
1044        }
1045/* -----------------------------------------------------------------------
1046$begin ta_free_available$$
1047$spell
1048        num
1049        thread_alloc
1050$$
1051
1052$section Free Memory Currently Available for Quick Use by a Thread$$
1053$spell
1054        inuse
1055$$
1056
1057$index free_available, thread_alloc$$
1058$index thread_alloc, free_available$$
1059$index free, available$$
1060$index available, free$$
1061$index thread, free memory$$
1062
1063$head Syntax$$
1064$codei%thread_alloc::free_available(%thread%)%$$
1065
1066$head Purpose$$
1067Return to the system all the memory that is currently being
1068$cref/held/ta_hold_memory/$$ for quick use by the specified thread.
1069
1070$subhead Extra Memory$$
1071In the case where $icode%thread% > 0%$$,
1072some extra memory is used to track allocations by the specified thread.
1073If
1074$codei%
1075        thread_alloc::inuse(%thread%) == 0
1076%$$
1077the extra memory is also returned to the system.
1078
1079$head thread$$
1080This argument has prototype
1081$codei%
1082        size_t %thread%
1083%$$
1084Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$,
1085or the current execution mode must be sequential
1086(not $cref/parallel/ta_in_parallel/$$).
1087
1088$head Example$$
1089$cref thread_alloc.cpp$$
1090
1091$end
1092*/
1093        /*!
1094        Return all the memory being held as available for a thread to the system.
1095
1096        \param thread [in]
1097        this thread that will no longer have any available memory after this call.
1098        This must either be the thread currently executing, or we must be
1099        in sequential (not parallel) execution mode.
1100        */
1101        static void free_available(size_t thread)
1102        {       CPPAD_ASSERT_KNOWN(
1103                        thread < CPPAD_MAX_NUM_THREADS,
1104                        "Attempt to free memory for a thread >= CPPAD_MAX_NUM_THREADS"
1105                );
1106                CPPAD_ASSERT_KNOWN( 
1107                        thread == thread_num() || (! in_parallel()),
1108                        "Attempt to free memory for a different thread "
1109                        "while in parallel mode"
1110                );
1111       
1112                size_t num_cap = capacity_info()->number;
1113                if( num_cap == 0 )
1114                        return;
1115                const size_t*     capacity_vec  = capacity_info()->value;
1116                size_t c_index;
1117                thread_alloc_info* info = thread_info(thread);
1118                for(c_index = 0; c_index < num_cap; c_index++)
1119                {       size_t capacity = capacity_vec[c_index];
1120                        block_t* available_root = info->root_available_ + c_index;
1121                        void* v_ptr             = available_root->next_;
1122                        while( v_ptr != CPPAD_NULL )
1123                        {       block_t* node = reinterpret_cast<block_t*>(v_ptr); 
1124                                void* next    = node->next_;
1125                                ::operator delete(v_ptr);
1126                                v_ptr         = next;
1127
1128                                dec_available(capacity, thread);
1129                        }
1130                        available_root->next_ = CPPAD_NULL;
1131                }
1132                CPPAD_ASSERT_UNKNOWN( available(thread) == 0 );
1133                if( inuse(thread) == 0 )
1134                {       // clear the information for this thread
1135                        thread_info(thread, true);
1136                }
1137        }
1138/* -----------------------------------------------------------------------
1139$begin ta_hold_memory$$
1140$spell
1141        alloc
1142        num
1143$$
1144
1145$section Control When Thread Alloc Retains Memory For Future Use$$
1146$index thread_alloc, hold memory$$
1147$index hold, thread_alloc memory$$
1148$index memory, thread_alloc hold$$
1149
1150$head Syntax$$
1151$codei%thread_alloc::hold_memory(%value%)%$$
1152
1153$head Purpose$$
1154It should be faster, even when $icode num_thread$$ is equal to one,
1155for $code thread_alloc$$ to hold onto memory.
1156Calling $icode hold_memory$$ with $icode value$$ equal to true,
1157instructs $code thread_alloc$$ to hold onto memory,
1158and put it in the $cref/available/ta_available/$$ pool,
1159after each call to $cref/return_memory/ta_return_memory/$$.
1160
1161$head value$$
1162If $icode value$$ is true,
1163$code thread_alloc$$ with hold onto memory for future quick use.
1164If it is false, future calls to $cref/return_memory/ta_return_memory/$$
1165will return the corresponding memory to the system.
1166By default (when $code hold_memory$$ has not been called)
1167$code thread_alloc$$ does not hold onto memory.
1168
1169$head free_available$$
1170Memory that is being held by $code thread_alloc$$ can be returned
1171to the system using $cref/free_available/ta_free_available/$$.
1172
1173$end
1174*/
1175        /*!
1176        Change the thread_alloc hold memory setting.
1177
1178        \param value [in]
1179        New value for the thread_alloc hold memory setting.
1180        */
1181        static void hold_memory(bool value)
1182        {       bool set = true;
1183                set_get_hold_memory(set, value);
1184        }       
1185       
1186/* -----------------------------------------------------------------------
1187$begin ta_inuse$$
1188$spell
1189        num
1190        inuse
1191        thread_alloc
1192$$
1193
1194$section Amount of Memory a Thread is Currently Using$$
1195
1196$index inuse, thread_alloc$$
1197$index thread_alloc, inuse$$
1198$index use, memory$$
1199$index thread, memory inuse$$
1200
1201$head Syntax$$
1202$icode%num_bytes% = thread_alloc::inuse(%thread%)%$$
1203
1204$head Purpose$$
1205Memory being managed by $cref thread_alloc$$ has two states,
1206currently in use by the specified thread,
1207and quickly available for future use by the specified thread.
1208This function informs the program how much memory is in use.
1209
1210$head thread$$
1211This argument has prototype
1212$codei%
1213        size_t %thread%
1214%$$
1215Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$,
1216or the current execution mode must be sequential
1217(not $cref/parallel/ta_in_parallel/$$).
1218
1219$head num_bytes$$
1220The return value has prototype
1221$codei%
1222        size_t %num_bytes%
1223%$$
1224It is the number of bytes currently in use by the specified thread.
1225
1226$head Example$$
1227$cref thread_alloc.cpp$$
1228
1229$end
1230*/
1231        /*!
1232        Determine the amount of memory that is currently inuse.
1233
1234        \param thread [in]
1235        Thread for which we are determining the amount of memory
1236        (must be < CPPAD_MAX_NUM_THREADS).
1237        Durring parallel execution, this must be the thread
1238        that is currently executing.
1239
1240        \return
1241        The amount of memory in bytes.
1242        */
1243        static size_t inuse(size_t thread)
1244        { 
1245                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);
1246                CPPAD_ASSERT_UNKNOWN( 
1247                        thread == thread_num() || (! in_parallel()) 
1248                );
1249                thread_alloc_info* info = thread_info(thread);
1250                return info->count_inuse_;
1251        }
1252/* -----------------------------------------------------------------------
1253$begin ta_available$$
1254$spell
1255        num
1256        thread_alloc
1257$$
1258
1259$section Amount of Memory Available for Quick Use by a Thread$$
1260
1261$index available, thread_alloc$$
1262$index thread_alloc, available$$
1263$index memory, available$$
1264$index thread, available memory$$
1265
1266$head Syntax$$
1267$icode%num_bytes% = thread_alloc::available(%thread%)%$$
1268
1269$head Purpose$$
1270Memory being managed by $cref thread_alloc$$ has two states,
1271currently in use by the specified thread,
1272and quickly available for future use by the specified thread.
1273This function informs the program how much memory is available.
1274
1275$head thread$$
1276This argument has prototype
1277$codei%
1278        size_t %thread%
1279%$$
1280Either $cref/thread_num/ta_thread_num/$$ must be the same as $icode thread$$,
1281or the current execution mode must be sequential
1282(not $cref/parallel/ta_in_parallel/$$).
1283
1284$head num_bytes$$
1285The return value has prototype
1286$codei%
1287        size_t %num_bytes%
1288%$$
1289It is the number of bytes currently available for use by the specified thread.
1290
1291$head Example$$
1292$cref thread_alloc.cpp$$
1293
1294$end
1295*/
1296        /*!
1297        Determine the amount of memory that is currently available for use.
1298
1299        \copydetails inuse
1300        */
1301        static size_t available(size_t thread)
1302        {
1303                CPPAD_ASSERT_UNKNOWN( thread < CPPAD_MAX_NUM_THREADS);
1304                CPPAD_ASSERT_UNKNOWN( 
1305                        thread == thread_num() || (! in_parallel()) 
1306                );
1307                thread_alloc_info* info = thread_info(thread);
1308                return info->count_available_;
1309        }
1310/* -----------------------------------------------------------------------
1311$begin ta_create_array$$
1312$spell
1313        inuse
1314        thread_alloc
1315        sizeof
1316$$
1317
1318$section Allocate An Array and Call Default Constructor for its Elements$$
1319
1320$index create_array, thread_alloc$$
1321$index thread_alloc, create_array$$
1322$index array, allocate$$
1323$index allocate, array$$
1324
1325$head Syntax$$
1326$icode%array% = thread_alloc::create_array<%Type%>(%size_min%, %size_out%)%$$.
1327
1328$head Purpose$$
1329Create a new raw array using $cref thread_alloc$$ memory allocator
1330(works well in a multi-threading environment)
1331and call default constructor for each element.
1332
1333$head Type$$
1334The type of the elements of the array.
1335
1336$head size_min$$
1337This argument has prototype
1338$codei%
1339        size_t %size_min%
1340%$$
1341This is the minimum number of elements that there can be
1342in the resulting $icode array$$.
1343
1344$head size_out$$
1345This argument has prototype
1346$codei%
1347        size_t& %size_out%
1348%$$
1349The input value of this argument does not matter.
1350Upon return, it is the actual number of elements
1351in $icode array$$
1352($icode% size_min %<=% size_out%$$).
1353
1354$head array$$
1355The return value $icode array$$ has prototype
1356$codei%
1357        %Type%* %array%
1358%$$
1359It is array with $icode size_out$$ elements.
1360The default constructor for $icode Type$$ is used to initialize the
1361elements of $icode array$$.
1362Note that $cref/delete_array/ta_delete_array/$$
1363should be used to destroy the array when it is no longer needed.
1364
1365$head Delta$$
1366The amount of memory $cref/inuse/ta_inuse/$$ by the current thread,
1367will increase $icode delta$$ where
1368$codei%
1369        sizeof(%Type%) * (%size_out% + 1) > %delta% >= sizeof(%Type%) * %size_out%
1370%$$
1371The $cref/available/ta_available/$$ memory will decrease by $icode delta$$,
1372(and the allocation will be faster)
1373if a previous allocation with $icode size_min$$ between its current value
1374and $icode size_out$$ is available.
1375
1376$head Example$$
1377$cref thread_alloc.cpp$$
1378
1379$end
1380*/
1381        /*!
1382        Use thread_alloc to allocate an array, then call default construtor
1383        for each element.
1384
1385        \tparam Type
1386        The type of the elements of the array.
1387
1388        \param size_min [in]
1389        The minimum number of elements in the array.
1390
1391        \param size_out [out]
1392        The actual number of elements in the array.
1393
1394        \return
1395        pointer to the first element of the array.
1396        The default constructor is used to initialize
1397        all the elements of the array.
1398
1399        \par
1400        The \c extra_ field, in the \c thread_alloc node before the return value,
1401        is set to size_out.
1402        */
1403        template <class Type>
1404        static Type* create_array(size_t size_min, size_t& size_out)
1405        {       // minimum number of bytes to allocate
1406                size_t min_bytes = size_min * sizeof(Type);
1407                // do the allocation
1408                size_t num_bytes;
1409                void*  v_ptr     = get_memory(min_bytes, num_bytes);
1410                // This is where the array starts
1411                Type*  array     = reinterpret_cast<Type*>(v_ptr);
1412                // number of Type values in the allocation
1413                size_out         = num_bytes / sizeof(Type);
1414                // store this number in the extra field
1415                block_t* node    = reinterpret_cast<block_t*>(v_ptr) - 1;
1416                node->extra_     = size_out;
1417
1418                // call default constructor for each element
1419                size_t i;
1420                for(i = 0; i < size_out; i++)
1421                        new(array + i) Type();
1422
1423                return array;
1424        }
1425/* -----------------------------------------------------------------------
1426$begin ta_delete_array$$
1427$spell
1428        inuse
1429        thread_alloc
1430        sizeof
1431        deallocate
1432$$
1433
1434$section Deallocate An Array and Call Destructor for its Elements$$
1435
1436$index delete_array, thread_alloc$$
1437$index thread_alloc, delete_array$$
1438$index array, allocate$$
1439$index allocate, array$$
1440
1441$head Syntax$$
1442$codei%thread_alloc::delete_array(%array%)%$$.
1443
1444$head Purpose$$
1445Returns memory corresponding to an array created by
1446(create by $cref/create_array/ta_create_array/$$) to the
1447$cref/available/ta_available/$$ memory pool for the current thread.
1448
1449$head Type$$
1450The type of the elements of the array.
1451
1452$head array$$
1453The argument $icode array$$ has prototype
1454$codei%
1455        %Type%* %array%
1456%$$
1457It is a value returned by $cref/create_array/ta_create_array/$$ and not yet deleted.
1458The $icode Type$$ destructor is called for each element in the array.
1459
1460$head Thread$$
1461The $cref/current thread/ta_thread_num/$$ must be the
1462same as when $cref/create_array/ta_create_array/$$ returned the value $icode array$$.
1463There is an exception to this rule:
1464when the current execution mode is sequential
1465(not $cref/parallel/ta_in_parallel/$$) the current thread number does not matter.
1466
1467$head Delta$$
1468The amount of memory $cref/inuse/ta_inuse/$$ will decrease by $icode delta$$,
1469and the $cref/available/ta_available/$$ memory will increase by $icode delta$$,
1470where $cref/delta/ta_create_array/Delta/$$
1471is the same as for the corresponding call to $code create_array$$.
1472
1473$head Example$$
1474$cref thread_alloc.cpp$$
1475
1476$end
1477*/
1478        /*!
1479        Return Memory Used for an Array to the Available Pool
1480        (include destructor call for each element).
1481
1482        \tparam Type
1483        The type of the elements of the array.
1484
1485        \param array [in]
1486        A value returned by \c create_array that has not yet been deleted.
1487        The \c Type destructor is used to destroy each of the elements
1488        of the array.
1489
1490        \par
1491        Durring parallel execution, the current thread must be the same
1492        as during the corresponding call to \c create_array.
1493        */
1494        template <class Type>
1495        static void delete_array(Type* array)
1496        {       // determine the number of values in the array
1497                block_t* node = reinterpret_cast<block_t*>(array) - 1;
1498                size_t size     = node->extra_;
1499
1500                // call destructor for each element
1501                size_t i;
1502                for(i = 0; i < size; i++)
1503                        (array + i)->~Type();
1504
1505                // return the memory to the available pool for this thread
1506                thread_alloc::return_memory( reinterpret_cast<void*>(array) );
1507        }
1508/* -----------------------------------------------------------------------
1509$begin ta_free_all$$
1510$spell
1511        alloc
1512        bool
1513        inuse
1514$$
1515
1516$section Free All Memory That Was Allocated for Use by thread_alloc$$
1517
1518$index free, all thread_alloc$$
1519$index thread_alloc, free all$$
1520
1521$head Syntax$$
1522$icode%ok% = thread_alloc::free_all()%$$.
1523
1524$head Purpose$$
1525Returns all memory that was used by $code thread_alloc$$ to the system.
1526
1527$head ok$$
1528The return value $icode ok$$ has prototype
1529$codei%
1530        bool %ok%
1531%$$
1532Its value will be $code true$$ if all the memory can be freed.
1533This requires that for all $icode thread$$ indices, there is no memory
1534$cref/inuse/ta_inuse/$$; i.e.,
1535$codei%
1536        0 == thread_alloc::inuse(%thread%)
1537%$$
1538Otherwise, the return value will be false.
1539
1540$head Restrictions$$
1541This function cannot be called while in parallel mode.
1542
1543$head Example$$
1544$cref thread_alloc.cpp$$
1545$end
1546*/
1547        /*!
1548        Return to the system all thread_alloc memory that is not currently inuse.
1549
1550        \return
1551        If no \c thread_alloc memory is currently inuse,
1552        all memory is returned to the system and the return value is true.
1553        Otherwise the return value is false.
1554        */
1555        static bool free_all(void)
1556        {       CPPAD_ASSERT_KNOWN(
1557                        ! in_parallel(),
1558                        "free_all cannot be used while in parallel execution"
1559                );
1560                bool ok = true;
1561                size_t thread = CPPAD_MAX_NUM_THREADS;
1562                while(thread--)
1563                {       ok &= inuse(thread) == 0;
1564                        free_available(thread);
1565                }
1566                return ok;
1567        }
1568};
1569
1570
1571/*! \} */
1572} // END_CPPAD_NAMESPACE
1573
1574// preprocessor symbols local to this file
1575# undef CPPAD_MAX_NUM_CAPACITY
1576# undef CPPAD_MIN_DOUBLE_CAPACITY
1577# undef CPPAD_TRACE_CAPACITY
1578# undef CPPAD_TRACE_THREAD
1579# endif
Note: See TracBrowser for help on using the repository browser.