mirror of
https://github.com/boostorg/build.git
synced 2026-02-21 15:02:19 +00:00
Fix memory leak in targets lists.
This changes the pointer type used everywhere for _targets/TARGETS to a unique_ptr to manage the ownership correctly. Thus removing the memory leaks resulting therein.
This commit is contained in:
@@ -563,7 +563,7 @@ LIST * builtin_depends( FRAME * frame, int flags )
|
||||
if ( flags )
|
||||
target_include_many( t, sources );
|
||||
else
|
||||
t->depends = targetlist( t->depends, sources );
|
||||
targetlist( t->depends, sources );
|
||||
}
|
||||
|
||||
/* Enter reverse links */
|
||||
@@ -577,11 +577,11 @@ LIST * builtin_depends( FRAME * frame, int flags )
|
||||
LISTITER t_iter = list_begin( targets );
|
||||
LISTITER const t_end = list_end( targets );
|
||||
for ( ; t_iter != t_end; t_iter = list_next( t_iter ) )
|
||||
s->dependants = targetentry( s->dependants, bindtarget(
|
||||
targetentry( s->dependants, bindtarget(
|
||||
list_item( t_iter ) )->includes );
|
||||
}
|
||||
else
|
||||
s->dependants = targetlist( s->dependants, targets );
|
||||
targetlist( s->dependants, targets );
|
||||
}
|
||||
|
||||
return L0;
|
||||
@@ -604,7 +604,7 @@ LIST * builtin_rebuilds( FRAME * frame, int flags )
|
||||
for ( ; iter != end; iter = list_next( iter ) )
|
||||
{
|
||||
TARGET * const t = bindtarget( list_item( iter ) );
|
||||
t->rebuilds = targetlist( t->rebuilds, rebuilds );
|
||||
targetlist( t->rebuilds, rebuilds );
|
||||
}
|
||||
return L0;
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ void cmdlist_free( CMDLIST * l )
|
||||
|
||||
CMD * cmd_new( RULE * rule, LIST * targets, LIST * sources, LIST * shell )
|
||||
{
|
||||
CMD * cmd = (CMD *)BJAM_MALLOC( sizeof( CMD ) );
|
||||
CMD * cmd = b2::jam::make_ptr<CMD>();
|
||||
FRAME frame[ 1 ];
|
||||
|
||||
assert( cmd );
|
||||
@@ -101,8 +101,7 @@ void cmd_free( CMD * cmd )
|
||||
lol_free( &cmd->args );
|
||||
list_free( cmd->shell );
|
||||
string_free( cmd->buf );
|
||||
freetargets( cmd->unlock );
|
||||
BJAM_FREE( (void *)cmd );
|
||||
b2::jam::free_ptr( cmd );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "lists.h"
|
||||
#include "mem.h"
|
||||
#include "rules.h"
|
||||
#include "jam_strings.h"
|
||||
|
||||
@@ -86,7 +87,7 @@ struct _cmd
|
||||
int noop; /* no-op commands should be faked instead of executed */
|
||||
int asynccnt; /* number of outstanding dependencies */
|
||||
targets_ptr lock; /* semaphores that are required by this cmd. */
|
||||
targets_ptr unlock; /* semaphores that are released when this cmd finishes. */
|
||||
targets_uptr unlock; /* semaphores that are released when this cmd finishes. */
|
||||
char status; /* the command status */
|
||||
};
|
||||
|
||||
|
||||
@@ -110,12 +110,11 @@ LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame )
|
||||
targets_ptr t;
|
||||
|
||||
/* The action is associated with this instance of this rule. */
|
||||
ACTION * const action = (ACTION *)BJAM_MALLOC( sizeof( ACTION ) );
|
||||
memset( (char *)action, '\0', sizeof( *action ) );
|
||||
ACTION * const action = b2::jam::make_ptr<ACTION>();
|
||||
|
||||
action->rule = rule;
|
||||
action->targets = targetlist( (targets_ptr)0, lol_get( frame->args, 0 ) );
|
||||
action->sources = targetlist( (targets_ptr)0, lol_get( frame->args, 1 ) );
|
||||
action->targets.reset(); targetlist( action->targets, lol_get( frame->args, 0 ) );
|
||||
action->sources.reset(); targetlist( action->sources, lol_get( frame->args, 1 ) );
|
||||
action->refs = 1;
|
||||
|
||||
/* If we have a group of targets all being built using the same action
|
||||
@@ -126,15 +125,15 @@ LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame )
|
||||
if ( action->targets )
|
||||
{
|
||||
TARGET * const t0 = action->targets->target;
|
||||
for ( t = action->targets->next; t; t = t->next )
|
||||
for ( t = action->targets->next.get(); t; t = t->next.get() )
|
||||
{
|
||||
t->target->rebuilds = targetentry( t->target->rebuilds, t0 );
|
||||
t0->rebuilds = targetentry( t0->rebuilds, t->target );
|
||||
targetentry( t->target->rebuilds, t0 );
|
||||
targetentry( t0->rebuilds, t->target );
|
||||
}
|
||||
}
|
||||
|
||||
/* Append this action to the actions of each target. */
|
||||
for ( t = action->targets; t; t = t->next )
|
||||
for ( t = action->targets.get(); t; t = t->next.get() )
|
||||
t->target->actions = actionlist( t->target->actions, action );
|
||||
|
||||
action_free( action );
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
# define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
static targets_ptr make0sort( targets_ptr c );
|
||||
static targets_uptr make0sort( targets_uptr c );
|
||||
|
||||
#ifdef OPT_GRAPH_DEBUG_EXT
|
||||
static void dependGraphOutput( TARGET * t, int32_t depth );
|
||||
@@ -174,7 +174,7 @@ static void update_dependants( TARGET * t )
|
||||
{
|
||||
targets_ptr q;
|
||||
|
||||
for ( q = t->dependants; q; q = q->next )
|
||||
for ( q = t->dependants.get(); q; q = q->next.get() )
|
||||
{
|
||||
TARGET * p = q->target;
|
||||
char fate0 = p->fate;
|
||||
@@ -211,7 +211,7 @@ static void update_dependants( TARGET * t )
|
||||
static void force_rebuilds( TARGET * t )
|
||||
{
|
||||
targets_ptr d;
|
||||
for ( d = t->rebuilds; d; d = d->next )
|
||||
for ( d = t->rebuilds.get(); d; d = d->next.get() )
|
||||
{
|
||||
TARGET * r = d->target;
|
||||
|
||||
@@ -250,7 +250,7 @@ int32_t make0rescan( TARGET * t, TARGET * rescanning )
|
||||
return 0;
|
||||
|
||||
t->rescanning = rescanning;
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
{
|
||||
TARGET * dependency = c->target;
|
||||
/* Always start at the root of each new strongly connected component. */
|
||||
@@ -265,7 +265,7 @@ int32_t make0rescan( TARGET * t, TARGET * rescanning )
|
||||
if ( result && t->scc_root == NULL )
|
||||
{
|
||||
t->scc_root = rescanning;
|
||||
rescanning->depends = targetentry( rescanning->depends, t );
|
||||
targetentry( rescanning->depends, t );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -408,7 +408,7 @@ void make0
|
||||
*/
|
||||
|
||||
/* Step 3a: Recursively make0() dependencies. */
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
{
|
||||
int32_t const internal = t->flags & T_FLAG_INTERNAL;
|
||||
|
||||
@@ -442,20 +442,20 @@ void make0
|
||||
|
||||
/* Step 3c: Add dependencies' includes to our direct dependencies. */
|
||||
{
|
||||
targets_ptr incs = 0;
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
targets_uptr incs;
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
if ( c->target->includes )
|
||||
incs = targetentry( incs, c->target->includes );
|
||||
t->depends = targetchain( t->depends, incs );
|
||||
targetentry( incs, c->target->includes );
|
||||
t->depends = targetchain( std::move(t->depends), std::move(incs) );
|
||||
}
|
||||
|
||||
if ( located_target )
|
||||
t->depends = targetentry( t->depends, located_target );
|
||||
targetentry( t->depends, located_target );
|
||||
|
||||
/* Step 3d: Detect cycles. */
|
||||
{
|
||||
int32_t cycle_depth = depth;
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
{
|
||||
TARGET * scc_root = target_scc( c->target );
|
||||
if ( scc_root->fate == T_FATE_MAKING &&
|
||||
@@ -479,7 +479,7 @@ void make0
|
||||
timestamp_clear( &last );
|
||||
timestamp_clear( &leaf );
|
||||
fate = T_FATE_STABLE;
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
{
|
||||
/* If we are in a different strongly connected component, pull
|
||||
* timestamps from the root.
|
||||
@@ -700,7 +700,7 @@ void make0
|
||||
targets_ptr c;
|
||||
for ( a = t->actions; a; a = a->next )
|
||||
{
|
||||
for ( c = a->action->targets; c; c = c->next )
|
||||
for ( c = a->action->targets.get(); c; c = c->next.get() )
|
||||
{
|
||||
if ( c->target->fate == T_FATE_INIT )
|
||||
{
|
||||
@@ -721,7 +721,7 @@ void make0
|
||||
*/
|
||||
|
||||
if ( globs.newestfirst )
|
||||
t->depends = make0sort( t->depends );
|
||||
t->depends = make0sort( std::move(t->depends) );
|
||||
|
||||
/*
|
||||
* Step 6: A little harmless tabulating for tracing purposes.
|
||||
@@ -862,7 +862,7 @@ static void dependGraphOutput( TARGET * t, int32_t depth )
|
||||
out_printf( "\n" );
|
||||
}
|
||||
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
{
|
||||
out_printf( " %s : Depends on %s (%s)", spaces( depth ),
|
||||
target_name( c->target ), target_fate[ (int32_t)c->target->fate ] );
|
||||
@@ -871,7 +871,7 @@ static void dependGraphOutput( TARGET * t, int32_t depth )
|
||||
out_printf( "\n" );
|
||||
}
|
||||
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
dependGraphOutput( c->target, depth + 1 );
|
||||
}
|
||||
#endif
|
||||
@@ -880,42 +880,31 @@ static void dependGraphOutput( TARGET * t, int32_t depth )
|
||||
/*
|
||||
* make0sort() - reorder TARGETS chain by their time (newest to oldest).
|
||||
*
|
||||
* We walk chain, taking each item and inserting it on the sorted result, with
|
||||
* newest items at the front. This involves updating each of the TARGETS'
|
||||
* c->next and c->tail. Note that we make c->tail a valid prev pointer for every
|
||||
* entry. Normally, it is only valid at the head, where prev == tail. Note also
|
||||
* that while tail is a loop, next ends at the end of the chain.
|
||||
* This sorts in-place by swapping the target pointers in the chain in a
|
||||
* rather terrible n-square/2 algorithm.
|
||||
*/
|
||||
|
||||
static targets_ptr make0sort( targets_ptr chain )
|
||||
static targets_uptr make0sort( targets_uptr chain )
|
||||
{
|
||||
PROFILE_ENTER( MAKE_MAKE0SORT );
|
||||
|
||||
targets_ptr result = 0;
|
||||
|
||||
/* Walk the current target list. */
|
||||
while ( chain )
|
||||
// The current tail we put the next newest item.
|
||||
for ( targets_ptr front = chain.get(); front ; front = front->next.get() )
|
||||
{
|
||||
targets_ptr c = chain;
|
||||
targets_ptr s = result;
|
||||
|
||||
chain = chain->next;
|
||||
|
||||
/* Find point s in result for c. */
|
||||
while ( s && timestamp_cmp( &s->target->time, &c->target->time ) > 0 )
|
||||
s = s->next;
|
||||
|
||||
/* Insert c in front of s (might be 0). */
|
||||
c->next = s; /* good even if s = 0 */
|
||||
if ( result == s ) result = c; /* new head of chain? */
|
||||
if ( !s ) s = result; /* wrap to ensure a next */
|
||||
if ( result != c ) s->tail->next = c; /* not head? be prev's next */
|
||||
c->tail = s->tail; /* take on next's prev */
|
||||
s->tail = c; /* make next's prev us */
|
||||
// Find the maximum time, i.e. most recent in the rest of the chain.
|
||||
targets_ptr newest = front->next.get();
|
||||
for ( targets_ptr rest = newest; rest ; rest = rest->next.get())
|
||||
{
|
||||
if ( timestamp_cmp( &newest->target->time, &rest->target->time ) > 0 )
|
||||
newest = rest;
|
||||
}
|
||||
// Sort it to the front if needed.
|
||||
if ( front != newest )
|
||||
std::swap( front->target, newest->target );
|
||||
}
|
||||
|
||||
PROFILE_EXIT( MAKE_MAKE0SORT );
|
||||
return result;
|
||||
return chain;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -60,15 +60,15 @@
|
||||
#endif
|
||||
|
||||
static CMD * make1cmds ( TARGET * );
|
||||
static LIST * make1list ( LIST *, targets_ptr, int32_t flags );
|
||||
static LIST * make1list ( LIST *, const targets_uptr &, int32_t flags );
|
||||
static SETTINGS * make1settings ( struct module_t *, LIST * vars );
|
||||
static void make1bind ( TARGET * );
|
||||
static void push_cmds( CMDLIST * cmds, int32_t status );
|
||||
static int32_t cmd_sem_lock( TARGET * t );
|
||||
static void cmd_sem_unlock( TARGET * t );
|
||||
|
||||
static int32_t targets_contains( targets_ptr l, TARGET * t );
|
||||
static int32_t targets_equal( targets_ptr l1, targets_ptr l2 );
|
||||
static bool targets_contains( const targets_uptr & l, TARGET * t );
|
||||
static bool targets_equal( const targets_uptr & l1, const targets_uptr & l2 );
|
||||
|
||||
/* Ugly static - it is too hard to carry it through the callbacks. */
|
||||
|
||||
@@ -307,7 +307,7 @@ static void make1a( state * const pState )
|
||||
TARGET * const parent_scc = target_scc( pState->parent );
|
||||
if ( t != parent_scc )
|
||||
{
|
||||
t->parents = targetentry( t->parents, parent_scc );
|
||||
targetentry( t->parents, parent_scc );
|
||||
++parent_scc->asynccnt;
|
||||
}
|
||||
}
|
||||
@@ -345,7 +345,7 @@ static void make1a( state * const pState )
|
||||
{
|
||||
stack temp_stack = { NULL };
|
||||
targets_ptr c;
|
||||
for ( c = t->depends; c && !quit; c = c->next )
|
||||
for ( c = t->depends.get(); c && !quit; c = c->next.get() )
|
||||
push_state( &temp_stack, c->target, t, T_STATE_MAKE1A );
|
||||
push_stack_on_stack( &state_stack, &temp_stack );
|
||||
}
|
||||
@@ -398,7 +398,7 @@ static void make1b( state * const pState )
|
||||
if ( !globs.noexec )
|
||||
{
|
||||
targets_ptr c;
|
||||
for ( c = t->depends; c; c = c->next )
|
||||
for ( c = t->depends.get(); c; c = c->next.get() )
|
||||
if ( c->target->status > t->status && !( c->target->flags &
|
||||
T_FLAG_NOCARE ) )
|
||||
{
|
||||
@@ -683,9 +683,8 @@ static void make1c( state const * const pState )
|
||||
* cleaned up correctly.
|
||||
*/
|
||||
t->includes->includes = saved_includes;
|
||||
for ( c = t->dependants; c; c = c->next )
|
||||
c->target->depends = targetentry( c->target->depends,
|
||||
t->includes );
|
||||
for ( c = t->dependants.get(); c; c = c->next.get() )
|
||||
targetentry( c->target->depends, t->includes );
|
||||
/* Will be processed below. */
|
||||
additional_includes = t->includes;
|
||||
}
|
||||
@@ -696,7 +695,7 @@ static void make1c( state const * const pState )
|
||||
}
|
||||
|
||||
if ( additional_includes )
|
||||
for ( c = t->parents; c; c = c->next )
|
||||
for ( c = t->parents.get(); c; c = c->next.get() )
|
||||
push_state( &temp_stack, additional_includes, c->target,
|
||||
T_STATE_MAKE1A );
|
||||
|
||||
@@ -704,19 +703,18 @@ static void make1c( state const * const pState )
|
||||
{
|
||||
TARGET * const scc_root = target_scc( t );
|
||||
assert( scc_root->progress < T_MAKE_DONE );
|
||||
for ( c = t->parents; c; c = c->next )
|
||||
for ( c = t->parents.get(); c; c = c->next.get() )
|
||||
{
|
||||
if ( target_scc( c->target ) == scc_root )
|
||||
push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B
|
||||
);
|
||||
else
|
||||
scc_root->parents = targetentry( scc_root->parents,
|
||||
c->target );
|
||||
targetentry( scc_root->parents, c->target );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( c = t->parents; c; c = c->next )
|
||||
for ( c = t->parents.get(); c; c = c->next.get() )
|
||||
push_state( &temp_stack, c->target, NULL, T_STATE_MAKE1B );
|
||||
}
|
||||
|
||||
@@ -1173,7 +1171,7 @@ static CMD * make1cmds( TARGET * t )
|
||||
int32_t start = 0;
|
||||
int32_t chunk = length;
|
||||
int32_t cmd_count = 0;
|
||||
targets_ptr semaphores = NULL;
|
||||
targets_uptr semaphores;
|
||||
targets_ptr targets_iter;
|
||||
int32_t unique_targets;
|
||||
do
|
||||
@@ -1264,7 +1262,7 @@ static CMD * make1cmds( TARGET * t )
|
||||
a0->action->last_cmd = last_cmd;
|
||||
|
||||
unique_targets = 0;
|
||||
for ( targets_iter = a0->action->targets; targets_iter; targets_iter = targets_iter->next )
|
||||
for ( targets_iter = a0->action->targets.get(); targets_iter; targets_iter = targets_iter->next.get() )
|
||||
{
|
||||
if ( targets_contains( targets_iter->next, targets_iter->target ) )
|
||||
continue;
|
||||
@@ -1279,17 +1277,17 @@ static CMD * make1cmds( TARGET * t )
|
||||
|
||||
#if OPT_SEMAPHORE
|
||||
/* Collect semaphores */
|
||||
for ( targets_iter = a0->action->targets; targets_iter; targets_iter = targets_iter->next )
|
||||
for ( targets_iter = a0->action->targets.get(); targets_iter; targets_iter = targets_iter->next.get() )
|
||||
{
|
||||
TARGET * sem = targets_iter->target->semaphore;
|
||||
if ( sem )
|
||||
{
|
||||
if ( ! targets_contains( semaphores, sem ) )
|
||||
semaphores = targetentry( semaphores, sem );
|
||||
targetentry( semaphores, sem );
|
||||
}
|
||||
}
|
||||
( ( CMD * )a0->action->first_cmd )->lock = semaphores;
|
||||
( ( CMD * )a0->action->last_cmd )->unlock = semaphores;
|
||||
( ( CMD * )a0->action->first_cmd )->lock = semaphores.get();
|
||||
( ( CMD * )a0->action->last_cmd )->unlock = std::move(semaphores);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1316,9 +1314,10 @@ static CMD * make1cmds( TARGET * t )
|
||||
* make1list() - turn a list of targets into a LIST, for $(<) and $(>)
|
||||
*/
|
||||
|
||||
static LIST * make1list( LIST * l, targets_ptr targets, int32_t flags )
|
||||
static LIST * make1list( LIST * l, const targets_uptr & ts, int32_t flags )
|
||||
{
|
||||
for ( ; targets; targets = targets->next )
|
||||
targets_ptr targets = ts.get();
|
||||
for ( ; targets; targets = targets->next.get() )
|
||||
{
|
||||
TARGET * t = targets->target;
|
||||
|
||||
@@ -1419,24 +1418,27 @@ static void make1bind( TARGET * t )
|
||||
}
|
||||
|
||||
|
||||
static int32_t targets_contains( targets_ptr l, TARGET * t )
|
||||
static bool targets_contains( const targets_uptr & ts, TARGET * t )
|
||||
{
|
||||
for ( ; l; l = l->next )
|
||||
targets_ptr l = ts.get();
|
||||
for ( ; l; l = l->next.get() )
|
||||
{
|
||||
if ( t == l->target )
|
||||
{
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t targets_equal( targets_ptr l1, targets_ptr l2 )
|
||||
static bool targets_equal( const targets_uptr & ts1, const targets_uptr & ts2 )
|
||||
{
|
||||
for ( ; l1 && l2; l1 = l1->next, l2 = l2->next )
|
||||
targets_ptr l1 = ts1.get();
|
||||
targets_ptr l2 = ts2.get();
|
||||
for ( ; l1 && l2; l1 = l1->next.get(), l2 = l2->next.get() )
|
||||
{
|
||||
if ( l1->target != l2->target )
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return !l1 && !l2;
|
||||
}
|
||||
@@ -1451,19 +1453,19 @@ static int32_t cmd_sem_lock( TARGET * t )
|
||||
/* Check whether all the semaphores required for updating
|
||||
* this target are free.
|
||||
*/
|
||||
for ( iter = cmd->lock; iter; iter = iter->next )
|
||||
for ( iter = cmd->lock; iter; iter = iter->next.get() )
|
||||
{
|
||||
if ( iter->target->asynccnt > 0 )
|
||||
{
|
||||
if ( DEBUG_EXECCMD )
|
||||
out_printf( "SEM: %s is busy, delaying launch of %s\n",
|
||||
object_str( iter->target->name ), object_str( t->name ) );
|
||||
iter->target->parents = targetentry( iter->target->parents, t );
|
||||
targetentry( iter->target->parents, t );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* Lock the semaphores. */
|
||||
for ( iter = cmd->lock; iter; iter = iter->next )
|
||||
for ( iter = cmd->lock; iter; iter = iter->next.get() )
|
||||
{
|
||||
++iter->target->asynccnt;
|
||||
if ( DEBUG_EXECCMD )
|
||||
@@ -1483,7 +1485,7 @@ static void cmd_sem_unlock( TARGET * t )
|
||||
CMD * cmd = ( CMD * )t->cmds;
|
||||
targets_ptr iter;
|
||||
/* Release the semaphores. */
|
||||
for ( iter = cmd->unlock; iter; iter = iter->next )
|
||||
for ( iter = cmd->unlock.get(); iter; iter = iter->next.get() )
|
||||
{
|
||||
if ( DEBUG_EXECCMD )
|
||||
out_printf( "SEM: %s is now free\n", object_str(
|
||||
@@ -1491,19 +1493,14 @@ static void cmd_sem_unlock( TARGET * t )
|
||||
--iter->target->asynccnt;
|
||||
assert( iter->target->asynccnt <= 0 );
|
||||
}
|
||||
for ( iter = cmd->unlock; iter; iter = iter->next )
|
||||
for ( iter = cmd->unlock.get(); iter; iter = iter->next.get() )
|
||||
{
|
||||
/* Find a waiting target that's ready */
|
||||
while ( iter->target->parents )
|
||||
{
|
||||
targets_ptr first = iter->target->parents;
|
||||
TARGET * t1 = first->target;
|
||||
TARGET * t1 = iter->target->parents->target;
|
||||
|
||||
/* Pop the first waiting CMD */
|
||||
if ( first->next )
|
||||
first->next->tail = first->tail;
|
||||
iter->target->parents = first->next;
|
||||
BJAM_FREE( first );
|
||||
iter->target->parents = targets_pop(std::move(iter->target->parents));
|
||||
|
||||
if ( cmd_sem_lock( t1 ) )
|
||||
{
|
||||
|
||||
112
src/engine/mem.h
112
src/engine/mem.h
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006. Rene Rivera
|
||||
* Copyright 2006-2022 René Ferdinand Rivera Morell
|
||||
* Distributed under the Boost Software License, Version 1.0.
|
||||
* (See accompanying file LICENSE.txt or copy at
|
||||
* https://www.bfgroup.xyz/b2/LICENSE.txt)
|
||||
@@ -10,63 +10,63 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/* Standard C memory allocation. */
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#define bjam_malloc_x(s) malloc(s)
|
||||
#define bjam_calloc_x(n,s) calloc(n,s)
|
||||
#define bjam_realloc_x(p,s) realloc(p,s)
|
||||
#define bjam_free_x(p) free(p)
|
||||
#define bjam_malloc_x(s) std::malloc(s)
|
||||
#define bjam_calloc_x(n, s) std::calloc(n, s)
|
||||
#define bjam_realloc_x(p, s) std::realloc(p, s)
|
||||
#define bjam_free_x(p) std::free(p)
|
||||
|
||||
#ifndef bjam_malloc_atomic_x
|
||||
#define bjam_malloc_atomic_x(s) bjam_malloc_x(s)
|
||||
#define bjam_malloc_atomic_x(s) bjam_malloc_x(s)
|
||||
#endif
|
||||
#ifndef bjam_calloc_atomic_x
|
||||
#define bjam_calloc_atomic_x(n,s) bjam_calloc_x(n,s)
|
||||
#define bjam_calloc_atomic_x(n, s) bjam_calloc_x(n, s)
|
||||
#endif
|
||||
#ifndef bjam_mem_init_x
|
||||
#define bjam_mem_init_x()
|
||||
#define bjam_mem_init_x()
|
||||
#endif
|
||||
#ifndef bjam_mem_close_x
|
||||
#define bjam_mem_close_x()
|
||||
#define bjam_mem_close_x()
|
||||
#endif
|
||||
#ifndef bjam_malloc_raw_x
|
||||
#define bjam_malloc_raw_x(s) bjam_malloc_x(s)
|
||||
#define bjam_malloc_raw_x(s) bjam_malloc_x(s)
|
||||
#endif
|
||||
#ifndef bjam_calloc_raw_x
|
||||
#define bjam_calloc_raw_x(n,s) bjam_calloc_x(n,s)
|
||||
#define bjam_calloc_raw_x(n, s) bjam_calloc_x(n, s)
|
||||
#endif
|
||||
#ifndef bjam_realloc_raw_x
|
||||
#define bjam_realloc_raw_x(p,s) bjam_realloc_x(p,s)
|
||||
#define bjam_realloc_raw_x(p, s) bjam_realloc_x(p, s)
|
||||
#endif
|
||||
#ifndef bjam_free_raw_x
|
||||
#define bjam_free_raw_x(p) bjam_free_x(p)
|
||||
#define bjam_free_raw_x(p) bjam_free_x(p)
|
||||
#endif
|
||||
|
||||
#ifdef OPT_DEBUG_PROFILE
|
||||
/* Profile tracing of memory allocations. */
|
||||
#include "debug.h"
|
||||
/* Profile tracing of memory allocations. */
|
||||
#include "debug.h"
|
||||
|
||||
#define BJAM_MALLOC(s) (profile_memory(s), bjam_malloc_x(s))
|
||||
#define BJAM_MALLOC_ATOMIC(s) (profile_memory(s), bjam_malloc_atomic_x(s))
|
||||
#define BJAM_CALLOC(n,s) (profile_memory(n*s), bjam_calloc_x(n,s))
|
||||
#define BJAM_CALLOC_ATOMIC(n,s) (profile_memory(n*s), bjam_calloc_atomic_x(n,s))
|
||||
#define BJAM_REALLOC(p,s) (profile_memory(s), bjam_realloc_x(p,s))
|
||||
#define BJAM_MALLOC(s) (profile_memory(s), bjam_malloc_x(s))
|
||||
#define BJAM_MALLOC_ATOMIC(s) (profile_memory(s), bjam_malloc_atomic_x(s))
|
||||
#define BJAM_CALLOC(n, s) (profile_memory(n * s), bjam_calloc_x(n, s))
|
||||
#define BJAM_CALLOC_ATOMIC(n, s) (profile_memory(n * s), bjam_calloc_atomic_x(n, s))
|
||||
#define BJAM_REALLOC(p, s) (profile_memory(s), bjam_realloc_x(p, s))
|
||||
|
||||
#define BJAM_MALLOC_RAW(s) (profile_memory(s), bjam_malloc_raw_x(s))
|
||||
#define BJAM_CALLOC_RAW(n,s) (profile_memory(n*s), bjam_calloc_raw_x(n,s))
|
||||
#define BJAM_REALLOC_RAW(p,s) (profile_memory(s), bjam_realloc_raw_x(p,s))
|
||||
#define BJAM_MALLOC_RAW(s) (profile_memory(s), bjam_malloc_raw_x(s))
|
||||
#define BJAM_CALLOC_RAW(n, s) (profile_memory(n * s), bjam_calloc_raw_x(n, s))
|
||||
#define BJAM_REALLOC_RAW(p, s) (profile_memory(s), bjam_realloc_raw_x(p, s))
|
||||
#else
|
||||
/* No mem tracing. */
|
||||
#define BJAM_MALLOC(s) bjam_malloc_x(s)
|
||||
#define BJAM_MALLOC_ATOMIC(s) bjam_malloc_atomic_x(s)
|
||||
#define BJAM_CALLOC(n,s) bjam_calloc_x(n,s)
|
||||
#define BJAM_CALLOC_ATOMIC(n,s) bjam_calloc_atomic_x(n,s)
|
||||
#define BJAM_REALLOC(p,s) bjam_realloc_x(p,s)
|
||||
/* No mem tracing. */
|
||||
#define BJAM_MALLOC(s) bjam_malloc_x(s)
|
||||
#define BJAM_MALLOC_ATOMIC(s) bjam_malloc_atomic_x(s)
|
||||
#define BJAM_CALLOC(n, s) bjam_calloc_x(n, s)
|
||||
#define BJAM_CALLOC_ATOMIC(n, s) bjam_calloc_atomic_x(n, s)
|
||||
#define BJAM_REALLOC(p, s) bjam_realloc_x(p, s)
|
||||
|
||||
#define BJAM_MALLOC_RAW(s) bjam_malloc_raw_x(s)
|
||||
#define BJAM_CALLOC_RAW(n,s) bjam_calloc_raw_x(n,s)
|
||||
#define BJAM_REALLOC_RAW(p,s) bjam_realloc_raw_x(p,s)
|
||||
#define BJAM_MALLOC_RAW(s) bjam_malloc_raw_x(s)
|
||||
#define BJAM_CALLOC_RAW(n, s) bjam_calloc_raw_x(n, s)
|
||||
#define BJAM_REALLOC_RAW(p, s) bjam_realloc_raw_x(p, s)
|
||||
#endif
|
||||
|
||||
#define BJAM_MEM_INIT() bjam_mem_init_x()
|
||||
@@ -75,4 +75,48 @@
|
||||
#define BJAM_FREE(p) bjam_free_x(p)
|
||||
#define BJAM_FREE_RAW(p) bjam_free_raw_x(p)
|
||||
|
||||
namespace b2 {
|
||||
namespace jam {
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* ctor_ptr(void* p, Args&&... args)
|
||||
{
|
||||
std::memset(p, 0, sizeof(T));
|
||||
return new (p) T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
T* make_ptr(Args&&... args)
|
||||
{
|
||||
return ctor_ptr<T>(BJAM_MALLOC(sizeof(T)));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void free_ptr(T* p)
|
||||
{
|
||||
p->~T();
|
||||
BJAM_FREE(p);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct unique_jptr_deleter {
|
||||
void operator()(T* p) const
|
||||
{
|
||||
p->~T();
|
||||
BJAM_FREE(p);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
using unique_jptr = std::unique_ptr<T, unique_jptr_deleter<T>>;
|
||||
|
||||
template <typename T, typename... Args>
|
||||
unique_jptr<T> make_unique_jptr(Args&&... args)
|
||||
{
|
||||
return unique_jptr<T>(make_ptr<T>(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "hash.h"
|
||||
#include "lists.h"
|
||||
#include "object.h"
|
||||
#include "output.h"
|
||||
#include "parse.h"
|
||||
#include "pathsys.h"
|
||||
#include "search.h"
|
||||
@@ -59,8 +60,7 @@ static target_ptr get_target_includes( target_ptr const t )
|
||||
{
|
||||
if ( !t->includes )
|
||||
{
|
||||
target_ptr const i = (target_ptr)BJAM_MALLOC( sizeof( *t ) );
|
||||
memset( (char *)i, '\0', sizeof( *i ) );
|
||||
target_ptr const i = b2::jam::make_ptr<_target>();
|
||||
i->name = object_copy( t->name );
|
||||
i->boundname = object_copy( i->name );
|
||||
i->flags |= T_FLAG_NOTFILE | T_FLAG_INTERNAL;
|
||||
@@ -81,14 +81,14 @@ static target_ptr get_target_includes( target_ptr const t )
|
||||
void target_include( target_ptr const including, target_ptr const included )
|
||||
{
|
||||
target_ptr const internal = get_target_includes( including );
|
||||
internal->depends = targetentry( internal->depends, included );
|
||||
targetentry( internal->depends, included );
|
||||
}
|
||||
|
||||
void target_include_many( target_ptr const including, list_ptr const included_names
|
||||
)
|
||||
{
|
||||
target_ptr const internal = get_target_includes( including );
|
||||
internal->depends = targetlist( internal->depends, included_names );
|
||||
targetlist( internal->depends, included_names );
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ target_ptr bindtarget( object_ptr const target_name )
|
||||
t = (target_ptr)hash_insert( targethash, target_name, &found );
|
||||
if ( !found )
|
||||
{
|
||||
memset( (char *)t, '\0', sizeof( *t ) );
|
||||
b2::jam::ctor_ptr<_target>(t);
|
||||
t->name = object_copy( target_name );
|
||||
t->boundname = object_copy( t->name ); /* default for T_FLAG_NOTFILE */
|
||||
}
|
||||
@@ -237,13 +237,12 @@ target_ptr target_scc( target_ptr t )
|
||||
* targets list of target names
|
||||
*/
|
||||
|
||||
targets_ptr targetlist( targets_ptr chain, list_ptr target_names )
|
||||
void targetlist( targets_uptr& chain, list_ptr target_names )
|
||||
{
|
||||
LISTITER iter = list_begin( target_names );
|
||||
LISTITER const end = list_end( target_names );
|
||||
for ( ; iter != end; iter = list_next( iter ) )
|
||||
chain = targetentry( chain, bindtarget( list_item( iter ) ) );
|
||||
return chain;
|
||||
targetentry( chain, bindtarget( list_item( iter ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -255,17 +254,15 @@ targets_ptr targetlist( targets_ptr chain, list_ptr target_names )
|
||||
* target new target to append
|
||||
*/
|
||||
|
||||
targets_ptr targetentry( targets_ptr chain, target_ptr target )
|
||||
void targetentry( targets_uptr& chain, target_ptr target )
|
||||
{
|
||||
targets_ptr const c = (targets_ptr)BJAM_MALLOC( sizeof( TARGETS ) );
|
||||
auto c = b2::jam::make_unique_jptr<TARGETS>();
|
||||
c->target = target;
|
||||
|
||||
if ( !chain ) chain = c;
|
||||
else chain->tail->next = c;
|
||||
chain->tail = c;
|
||||
c->next = 0;
|
||||
|
||||
return chain;
|
||||
targets_ptr tail = c.get();
|
||||
if ( !chain ) chain.reset(c.release());
|
||||
else chain->tail->next.reset(c.release());
|
||||
chain->tail = tail;
|
||||
}
|
||||
|
||||
|
||||
@@ -277,13 +274,26 @@ targets_ptr targetentry( targets_ptr chain, target_ptr target )
|
||||
* target new target to append
|
||||
*/
|
||||
|
||||
targets_ptr targetchain( targets_ptr chain, targets_ptr targets )
|
||||
targets_uptr targetchain( targets_uptr chain, targets_uptr targets )
|
||||
{
|
||||
if ( !targets ) return chain;
|
||||
if ( !chain ) return targets;
|
||||
|
||||
chain->tail->next = targets;
|
||||
chain->tail = targets->tail;
|
||||
targets_ptr tail = targets->tail;
|
||||
chain->tail->next = std::move(targets);
|
||||
chain->tail = tail;
|
||||
return chain;
|
||||
}
|
||||
|
||||
/*
|
||||
* targets_pop() - removes the first TARGET from the chain.
|
||||
*/
|
||||
|
||||
targets_uptr targets_pop(targets_uptr chain)
|
||||
{
|
||||
if ( chain && chain->next )
|
||||
chain->next->tail = chain->tail;
|
||||
chain = std::move( chain->next );
|
||||
return chain;
|
||||
}
|
||||
|
||||
@@ -295,9 +305,7 @@ void action_free( action_ptr action )
|
||||
{
|
||||
if ( --action->refs == 0 )
|
||||
{
|
||||
freetargets( action->targets );
|
||||
freetargets( action->sources );
|
||||
BJAM_FREE( action );
|
||||
b2::jam::free_ptr(action);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,21 +416,6 @@ settings_ptr copysettings( settings_ptr head )
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* freetargets() - delete a targets list.
|
||||
*/
|
||||
|
||||
void freetargets( targets_ptr chain )
|
||||
{
|
||||
while ( chain )
|
||||
{
|
||||
targets_ptr const n = chain->next;
|
||||
BJAM_FREE( chain );
|
||||
chain = n;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* freeactions() - delete an action list.
|
||||
*/
|
||||
@@ -462,15 +455,16 @@ static void freetarget( target_ptr const t, void * )
|
||||
if ( t->name ) object_free ( t->name );
|
||||
if ( t->boundname ) object_free ( t->boundname );
|
||||
if ( t->settings ) freesettings( t->settings );
|
||||
if ( t->depends ) freetargets ( t->depends );
|
||||
if ( t->dependants ) freetargets ( t->dependants );
|
||||
if ( t->parents ) freetargets ( t->parents );
|
||||
if ( t->depends ) t->depends.reset();
|
||||
if ( t->dependants ) t->dependants.reset();
|
||||
if ( t->parents ) t->parents.reset();
|
||||
if ( t->actions ) freeactions ( t->actions );
|
||||
if ( t->includes )
|
||||
{
|
||||
freetarget( t->includes, (void *)0 );
|
||||
BJAM_FREE( t->includes );
|
||||
}
|
||||
t->~_target();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "function.h"
|
||||
#include "mem.h"
|
||||
#include "modules.h"
|
||||
#include "timestamp.h"
|
||||
|
||||
@@ -49,6 +50,20 @@ typedef ACTION* action_ptr;
|
||||
typedef ACTIONS* actions_ptr;
|
||||
typedef SETTINGS* settings_ptr;
|
||||
|
||||
typedef RULE& rule_ref;
|
||||
typedef TARGET& target_ref;
|
||||
typedef TARGETS& targets_ref;
|
||||
typedef ACTION& action_ref;
|
||||
typedef ACTIONS& actions_ref;
|
||||
typedef SETTINGS& settings_ref;
|
||||
|
||||
using rule_uptr = b2::jam::unique_jptr<_rule>;
|
||||
using target_uptr = b2::jam::unique_jptr<_target>;
|
||||
using targets_uptr = b2::jam::unique_jptr<_targets>;
|
||||
using action_uptr = b2::jam::unique_jptr<_action>;
|
||||
using actions_uptr = b2::jam::unique_jptr<_actions>;
|
||||
using settings_uptr = b2::jam::unique_jptr<_settings>;
|
||||
|
||||
/* RULE - a generic jam rule, the product of RULE and ACTIONS. */
|
||||
|
||||
/* Build actions corresponding to a rule. */
|
||||
@@ -89,8 +104,8 @@ struct _actions {
|
||||
/* ACTION - a RULE instance with targets and sources. */
|
||||
struct _action {
|
||||
rule_ptr rule;
|
||||
targets_ptr targets;
|
||||
targets_ptr sources; /* aka $(>) */
|
||||
targets_uptr targets;
|
||||
targets_uptr sources; /* aka $(>) */
|
||||
char running; /* has been started */
|
||||
#define A_INIT 0
|
||||
#define A_RUNNING_NOEXEC 1
|
||||
@@ -113,9 +128,9 @@ struct _settings {
|
||||
|
||||
/* TARGETS - a chain of TARGETs. */
|
||||
struct _targets {
|
||||
targets_ptr next;
|
||||
targets_ptr tail; /* valid only for head */
|
||||
target_ptr target;
|
||||
targets_uptr next = nullptr;
|
||||
targets_ptr tail = nullptr; /* valid only for head */
|
||||
target_ptr target = nullptr;
|
||||
};
|
||||
|
||||
/* TARGET - an entity (e.g. a file) that can be built. */
|
||||
@@ -125,11 +140,11 @@ struct _target {
|
||||
actions_ptr actions; /* rules to execute, if any */
|
||||
settings_ptr settings; /* variables to define */
|
||||
|
||||
targets_ptr depends; /* dependencies */
|
||||
targets_ptr dependants; /* the inverse of dependencies */
|
||||
targets_ptr rebuilds; /* targets that should be force-rebuilt
|
||||
* whenever this one is
|
||||
*/
|
||||
targets_uptr depends; /* dependencies */
|
||||
targets_uptr dependants; /* the inverse of dependencies */
|
||||
targets_uptr rebuilds; /* targets that should be force-rebuilt
|
||||
* whenever this one is
|
||||
*/
|
||||
target_ptr includes; /* internal includes node */
|
||||
|
||||
timestamp time; /* update time */
|
||||
@@ -217,7 +232,7 @@ struct _target {
|
||||
#endif
|
||||
|
||||
int asynccnt; /* child deps outstanding */
|
||||
targets_ptr parents; /* used by make1() for completion */
|
||||
targets_uptr parents; /* used by make1() for completion */
|
||||
target_ptr scc_root; /* used by make to resolve cyclic includes
|
||||
*/
|
||||
target_ptr rescanning; /* used by make0 to mark visited targets
|
||||
@@ -254,17 +269,17 @@ void rule_free(rule_ptr);
|
||||
/* Target related functions. */
|
||||
void bind_explicitly_located_targets();
|
||||
target_ptr bindtarget(object_ptr const);
|
||||
void freetargets(targets_ptr);
|
||||
targets_ptr targetchain(targets_ptr, targets_ptr);
|
||||
targets_ptr targetentry(targets_ptr, target_ptr);
|
||||
targets_uptr targetchain(targets_uptr, targets_uptr);
|
||||
void targetentry(targets_uptr&, target_ptr);
|
||||
void target_include(target_ptr const including,
|
||||
target_ptr const included);
|
||||
void target_include_many(target_ptr const including,
|
||||
list_ptr const included_names);
|
||||
targets_ptr targetlist(targets_ptr, list_ptr target_names);
|
||||
void targetlist(targets_uptr&, list_ptr target_names);
|
||||
void touch_target(object_ptr const);
|
||||
void clear_includes(target_ptr);
|
||||
target_ptr target_scc(target_ptr);
|
||||
targets_uptr targets_pop(targets_uptr);
|
||||
|
||||
/* Final module cleanup. */
|
||||
void rules_done();
|
||||
|
||||
Reference in New Issue
Block a user