• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nasa / trick / 10063374342

23 Jul 2024 05:16PM UTC coverage: 55.891% (+0.01%) from 55.879%
10063374342

push

github

web-flow
Speed up Trick::ScheduledJobQueue::push (#1694)

* Speed up Trick::ScheduledJobQueue::push

* Make comparator a static function

* Use upper_bound instead

* Use explicit types

* Update comment

* Fix formatting

29 of 30 new or added lines in 1 file covered. (96.67%)

1 existing line in 1 file now uncovered.

12291 of 21991 relevant lines covered (55.89%)

72916.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.71
/trick_source/sim_services/ScheduledJobQueue/ScheduledJobQueue.cpp
1
#include <algorithm>
2
#include <iostream>
3
#include <sstream>
4
#include <stdlib.h>
5
#include <stdio.h>
6
#include <string.h>
7

8
#include "trick/ScheduledJobQueue.hh"
9
#include "trick/ScheduledJobQueueInstrument.hh"
10
#include "trick/TrickConstant.hh"
11

12
/**
13
@design
14
-# Set #list to NULL
15
-# Set #list_list to 0
16
-# Set #curr_index to 0
17
-# Set #next_job_time to TRICK_MAX_LONG_LONG
18
*/
19
Trick::ScheduledJobQueue::ScheduledJobQueue( ) {
7,120✔
20

21
    list = NULL ;
7,120✔
22
    list_size = 0 ;
7,120✔
23
    curr_index = 0 ;
7,120✔
24
    next_job_time = TRICK_MAX_LONG_LONG ;
7,120✔
25

26
}
7,120✔
27

28
/**
29
@design
30
-# free list if it is not empty
31
*/
32
Trick::ScheduledJobQueue::~ScheduledJobQueue( ) {
14,240✔
33
    if (list  != NULL ) {
7,120✔
34
        free(list) ;
4,082✔
35
    }
36
}
7,120✔
37

38
static bool compare_job_data(const Trick::JobData *a, const Trick::JobData *b) {
54,203✔
39
    {
40
        int ajc = a->job_class;
54,203✔
41
        int bjc = b->job_class;
54,203✔
42
        if (ajc < bjc)
54,203✔
43
            return true;
4,113✔
44
        if (ajc > bjc)
50,090✔
45
            return false;
372✔
46
    }
47
    {
48
        unsigned short ap = a->phase;
49,718✔
49
        unsigned short bp = b->phase;
49,718✔
50
        if (ap < bp)
49,718✔
51
            return true;
16,109✔
52
        if (ap > bp)
33,609✔
53
            return false;
9,161✔
54
    }
55
    {
56
        int asoi = a->sim_object_id;
24,448✔
57
        int bsoi = b->sim_object_id;
24,448✔
58
        if (asoi < bsoi)
24,448✔
59
            return true;
3✔
60
        if (asoi > bsoi)
24,445✔
61
            return false;
15,569✔
62
    }
63
    return a->id < b->id;
8,876✔
64
}
65

66
/**
67
@design
68
-# Allocate additional memory for the incoming job
69
-# Find the insertion point in the queue based on the job_class, the phase,
70
   the sim_object id, and the job_id
71
-# Move the jobs after the insertion point to the right by one.
72
-# Insert the new job at the insertion point.
73
-# Increment the size of the queue.
74
*/
75
int Trick::ScheduledJobQueue::push( JobData * new_job ) {
24,936✔
76

77
    /* Allocate additional memory for the additional job in the queue */
78
    JobData ** new_list = (JobData **)realloc(list, (list_size + 1) * sizeof(JobData *)) ;
24,936✔
79
    if (!new_list) {
24,936✔
NEW
80
        abort();
×
81
    }
82
    list = new_list;
24,936✔
83
    JobData ** list_end = list + list_size;
24,936✔
84
    JobData ** insert_pt = std::upper_bound(list, list_end, new_job, compare_job_data);
24,936✔
85
    if (insert_pt != list_end) {
24,936✔
86
        memmove(insert_pt + 1, insert_pt, (list_end - insert_pt) * sizeof(JobData *));
9,742✔
87
    }
88
    *insert_pt = new_job;
24,936✔
89

90
    new_job->set_handled(true) ;
24,936✔
91

92
    /* Increment the size of the queue */
93
    list_size++ ;
24,936✔
94

95
    return(0) ;
24,936✔
96

97
}
98

99
/**
100
@design
101
-# Temporarily assign a high sim_object id to the incoming job.  This
102
   effectively removes the sim_object_id as an ordering field
103
-# Call Trick::ScheduledJobQueue::push( JobData * ) to add the job to the queue.
104
-# Restore the original sim_object id.
105
*/
106
int Trick::ScheduledJobQueue::push_ignore_sim_object( JobData * new_job ) {
55✔
107

108
    int save_sim_object_id ;
109
    int ret ;
110

111
    /* Temorarily assign a really high sim_object id  */
112
    save_sim_object_id = new_job->sim_object_id ;
55✔
113
    new_job->sim_object_id = 1000000 ;
55✔
114
    /* push the job onto the scheduling queue as normal */
115
    ret = push(new_job) ;
55✔
116
    /* restore the original sim_object id */
117
    new_job->sim_object_id = save_sim_object_id ;
55✔
118
    return(ret) ;
55✔
119
}
120

121
/**
122
@design
123
-# Traverse the list of jobs looking for the job to delete.
124
 -# If the job to delete is found
125
  -# Allocate a new list that holds 1 less job than the current list
126
  -# Copy all of the jobs that precede the deleted job to the new list
127
  -# Copy all of the jobs that are after the delete job to the new list
128
  -# Decrement the size of the list
129
  -# Free the memory associated with the current list
130
  -# Point the current list to the newly allocated list
131
*/
132
int Trick::ScheduledJobQueue::remove( JobData * delete_job ) {
×
133

134
    unsigned int ii , jj ;
135

136
    /* Find the job to delete in the queue. */
137
    for ( ii = 0 ; ii < list_size ; ii++ ) {
×
138
        if ( list[ii] == delete_job ) {
×
139
            /* allocate a new list that holds one less element than the current list. */
140
            JobData ** new_list = (JobData **)calloc( list_size - 1 , sizeof(JobData *)) ;
×
141
            /* copy all of the jobs that are before the deleted job to the new list */
142
            for ( jj = 0 ; jj < ii ; jj++ ) {
×
143
                new_list[jj] = list[jj] ;
×
144
            }
145
            /* copy all of the jobs that are after the deleted job to the new list */
146
            for ( jj = ii + 1 ; jj < list_size ; jj++ ) {
×
147
                new_list[jj-1] = list[jj] ;
×
148
            }
149
            if ( ii <= curr_index ) {
×
150
                curr_index-- ;
×
151
            }
152
            /* Decrement the size of the queue */
153
            list_size-- ;
×
154
            /* Free the old queue space */
155
            free(list) ;
×
156
            /* Assign the queue pointer to the new space */
157
            list = new_list ;
×
158
            return 0 ;
×
159
        }
160
    }
161
    return -1 ;
×
162
}
163

164
/**
165
@design
166
-# Returns the #curr_index of the queue.
167
*/
168
unsigned int Trick::ScheduledJobQueue::get_curr_index() {
3,244✔
169
    return curr_index ;
3,244✔
170
}
171

172
/**
173
@design
174
-# Sets #curr_index to the incoming value.
175
*/
176
int Trick::ScheduledJobQueue::set_curr_index(unsigned int value ) {
3,244✔
177

178
    if ( value < list_size ) {
3,244✔
179
        curr_index = value ;
2,196✔
180
    }
181
    return 0 ;
3,244✔
182
}
183

184
/**
185
@design
186
-# Sets #curr_index to 0.
187
*/
188
int Trick::ScheduledJobQueue::reset_curr_index() {
1,799,662✔
189

190
    curr_index = 0 ;
1,799,662✔
191
    return(0) ;
1,799,662✔
192
}
193

194
/**
195
@design
196
-# Returns #list_size
197
*/
198
unsigned int Trick::ScheduledJobQueue::size() {
220✔
199
    return(list_size) ;
220✔
200
}
201

202
/**
203
@design
204
-# Returns !(#list_size)
205
*/
206
bool Trick::ScheduledJobQueue::empty() {
154,699✔
207
    return(!list_size) ;
154,699✔
208
}
209

210
/**
211
@design
212
-# If #list is not NULL free it.
213
-# Set #list to NULL
214
-# Set #list_list to 0
215
-# Set #curr_index to 0
216
-# Set #next_job_time to TRICK_MAX_LONG_LONG
217
*/
218
int Trick::ScheduledJobQueue::clear() {
197✔
219

220
    /* free job list if one exists  */
221
    if (list != NULL ) {
197✔
222
        free(list) ;
176✔
223
    }
224
    /* set all list variables to initial cleared values */
225
    list = NULL ;
197✔
226
    list_size = 0 ;
197✔
227
    curr_index = 0 ;
197✔
228
    next_job_time = TRICK_MAX_LONG_LONG ;
197✔
229
    return(0) ;
197✔
230
}
231

232
/**
233
@design
234
-# If the list is empty return NULL
235
-# Else return the current job without incrementing the #curr_index index.
236
*/
237
Trick::JobData * Trick::ScheduledJobQueue::top() {
5✔
238
    /* return NULL if list is empty  */
239
    if ( list_size == 0 ) {
5✔
240
        return(NULL) ;
1✔
241
    }
242
    /* else return current list item  */
243
    return(list[curr_index]) ;
4✔
244
}
245

246

247
/**
248
@design
249
-# If the #curr_index is greater than or equal to the #list_size
250
    -# Set the #curr_index to the #list_size
251
    -# Return NULL
252
-# Else while the list #curr_list is less than the list size
253
    -# Increment the #curr_index.
254
    -# Return the current job if the job is enabled.
255
*/
256
Trick::JobData * Trick::ScheduledJobQueue::get_next_job() {
4,293,509✔
257

258
    JobData * curr_job ;
259

260
    /* return NULL if we are at the end of the list  */
261
    if ( curr_index >= list_size ) {
4,293,509✔
262
        curr_index = list_size ;
1,279,298✔
263
        return(NULL) ;
1,279,298✔
264
    } else {
265
        /* return the next enabled job, or NULL if we reach the end of the list */
266
        while (curr_index < list_size ) {
3,014,228✔
267
            curr_job = list[curr_index++] ;
3,014,228✔
268
            if ( !curr_job->disabled ) {
3,014,228✔
269
                return(curr_job) ;
3,014,211✔
270
            }
271
        }
272
    }
273
    return(NULL) ;
×
274
}
275

276
/**
277
@design
278
-# While the list #curr_list is less than the list size
279
    -# If the current queue job next call matches the incoming simulation time
280
        -# If the job class is not a system class job, calculate the next
281
           time it will be called by current time + job cycle.
282
        -# Set the next job call time to TRICK_MAX_LONG_LONG if the next job call time
283
           is greater than the stop time.
284
        -# If the job's next job call time is lower than the overall next job call time
285
           set the overall job call time to the current job's next job call time.
286
        -# Increment the #curr_index.
287
        -# Return the current job if the job is enabled.
288
    -# Else
289
        -# If the job's next job call time is lower than the overall next job call time
290
           set the overall job call time to the current job's next job call time.
291
        -# Increment the #curr_index.
292
-# Return NULL when the end of the list is reached.
293
*/
294
Trick::JobData * Trick::ScheduledJobQueue::find_next_job(long long time_tics ) {
3,273,979✔
295

296
    JobData * curr_job ;
297
    long long next_call ;
298

299
    /* Search through the rest of the queue starting at curr_index looking for
300
       the next job with it's next execution time is equal to the current simulation time. */
301
    while (curr_index < list_size ) {
3,273,979✔
302

303
        curr_job = list[curr_index] ;
2,756,488✔
304

305
        if ( curr_job->next_tics == time_tics ) {
2,756,488✔
306

307
            /* If the job does not reschedule itself (system_job_classes), calculate the next time it will be called. */
308
            if ( ! curr_job->system_job_class ) {
1,036,130✔
309
                // calculate the next job call time
310
                next_call = curr_job->next_tics + curr_job->cycle_tics ;
777,751✔
311
                /* If the next time does not exceed the stop time, set the next call time for the module */
312
                if (next_call > curr_job->stop_tics) {
777,751✔
313
                    curr_job->next_tics = TRICK_MAX_LONG_LONG ;
×
314
                } else {
315
                    curr_job->next_tics = next_call;
777,751✔
316
                }
317
                /* Track next lowest job call time after the current time for jobs that match the current time. */
318
                if ( curr_job->next_tics <  next_job_time ) {
777,751✔
319
                    next_job_time = curr_job->next_tics ;
169,834✔
320
                }
321
            }
322
            curr_index++ ;
1,036,130✔
323
            if ( !curr_job->disabled ) {
1,036,130✔
324
                return(curr_job) ;
949,715✔
325
            }
326
        } else {
327
            /* Track next lowest job call time after the current time for jobs that do not match the current time */
328
            if ( curr_job->next_tics > time_tics && curr_job->next_tics < next_job_time ) {
1,720,358✔
329
                next_job_time = curr_job->next_tics ;
15,805✔
330
            }
331
            curr_index++ ;
1,720,358✔
332
        }
333
    }
334
    return(NULL) ;
517,491✔
335
}
336

337
/**
338
@design
339
-# While the list #curr_list is less than the list size
340
    -# If the current queue job next call matches the incoming simulation time
341
        -# Increment the #curr_index.
342
        -# Return the current job if the job is enabled.
343
    -# Increment the #curr_index.
344
-# Return NULL when the end of the list is reached.
345
*/
346
Trick::JobData* Trick::ScheduledJobQueue::find_job(long long time_tics) {
24,716✔
347
    JobData * curr_job ;
348

349
    /* Search through the rest of the queue starting at curr_index looking for             */
350
    /* the next job with it's next execution time is equal to the current simulation time. */
351
    while (curr_index < list_size) {
24,716✔
352
        curr_job = list[curr_index] ;
21,884✔
353

354
        if (curr_job->next_tics == time_tics ) {
21,884✔
355
            if (!curr_job->disabled) {
5,451✔
356
                curr_index++ ;
5,451✔
357
                return(curr_job) ;
5,451✔
358
            }
359
        }
360
        curr_index++ ;
16,433✔
361
    }
362
    return(NULL) ;
2,832✔
363
}
364

365
/**
366
@details
367
-# Sets #next_job_time to the incoming time
368
*/
369
int Trick::ScheduledJobQueue::set_next_job_call_time(long long in_time) {
517,499✔
370
    next_job_time = in_time ;
517,499✔
371
    return(0) ;
517,499✔
372
}
373

374
/**
375
@details
376
-# Return the next_job_call_time in counts of tics/second
377
   Requirement [@ref r_exec_time_0]
378
*/
379
long long Trick::ScheduledJobQueue::get_next_job_call_time() {
685,682✔
380
    unsigned int temp_index = curr_index ;
685,682✔
381
    while (temp_index < list_size ) {
1,418,552✔
382
        if ( list[temp_index]->next_tics <  next_job_time ) {
732,870✔
383
            next_job_time = list[temp_index]->next_tics ;
12✔
384
        }
385
        temp_index++ ;
732,870✔
386
    }
387
    return(next_job_time) ;
685,682✔
388
}
389

390
/**
391
@details
392
-# If the current job next call time is less than the overall next job call time, and is
393
   greater than the current simulation time, set the overall next job call time to be the
394
   job next call time.
395
*/
396
int Trick::ScheduledJobQueue::test_next_job_call_time(Trick::JobData * curr_job, long long time_tics) {
258,386✔
397
    if ( curr_job->next_tics > time_tics && curr_job->next_tics < next_job_time ) {
258,386✔
398
        next_job_time = curr_job->next_tics ;
7✔
399
    }
400
    return(0) ;
258,386✔
401
}
402

403
// Executes the jobs in a queue.  saves and restores Trick::Executive::curr_job
404
int Trick::ScheduledJobQueue::execute_all_jobs() {
×
405
    Trick::JobData * curr_job ;
406
    int ret ;
407

408
    reset_curr_index() ;
×
409
    while ( (curr_job = get_next_job()) != NULL ) {
×
410
        ret = curr_job->call() ;
×
411
        if ( ret != 0 ) {
×
412
            return ret ;
×
413
        }
414
    }
415
    /* return 0 if there are no errors. */
416
    return 0 ;
×
417
}
418

419
int Trick::ScheduledJobQueue::write_sched_queue( FILE * fp ) {
1,795✔
420

421
    Trick::JobData * curr_job ;
422
    unsigned int save_index ;
423

424
    save_index = get_curr_index() ;
1,795✔
425
    reset_curr_index() ;
1,795✔
426
    while ( (curr_job = get_next_job()) != NULL ) {
4,853✔
427
        if ( curr_job->job_class_name.compare("instrumentation") ) {
3,058✔
428
            /* for each non instrumentation job write the job information to the open file pointer "fp" */
429
            fprintf(fp, "%7d | %3d |%-25s| %-5d | %08.6f | %8.6g | %8g | %5.02f | %s\n",
3,058✔
430
                    !curr_job->disabled, curr_job->thread, curr_job->job_class_name.c_str(), curr_job->phase,
3,058✔
431
                    curr_job->start, curr_job->cycle, curr_job->stop, curr_job->frame_id,
432
                    curr_job->name.c_str());
433
        }
434
    }
435
    set_curr_index(save_index) ;
1,795✔
436
    return(0) ;
1,795✔
437
}
438

439
int Trick::ScheduledJobQueue::write_non_sched_queue( FILE * fp ) {
1,440✔
440

441
    Trick::JobData * curr_job ;
442
    unsigned int save_index ;
443

444
    save_index = get_curr_index() ;
1,440✔
445
    reset_curr_index() ;
1,440✔
446
    while ( (curr_job = get_next_job()) != NULL ) {
15,223✔
447
        if ( curr_job->job_class_name.compare("instrumentation") ) {
13,783✔
448
            /* for each non instrumentation job write the job information to the open file pointer "fp" */
449
            fprintf(fp, "%7d | %3d |%-25s| %-5d |          |          |          | %5.02f | %s\n",
13,783✔
450
                    !curr_job->disabled, curr_job->thread, curr_job->job_class_name.c_str(), curr_job->phase,
13,783✔
451
                    curr_job->frame_id, curr_job->name.c_str());
452
        }
453
    }
454

455
    set_curr_index(save_index) ;
1,440✔
456
    return(0) ;
1,440✔
457
}
458

459
/**
460
@details
461
-# For all jobs in the queue
462
    -# Create a new ScheduledJobQueueInstrument instance
463
    -# Add the new instrumentation job to the "before" instrumentation job list
464
-# Return 0
465
*/
466
int Trick::ScheduledJobQueue::instrument_before(Trick::JobData * instrumentation_job) {
18✔
467

468
    unsigned int ii ;
469
    ScheduledJobQueueInstrument * new_job ;
470

471
    for ( ii = 0 ; ii < list_size ; ii++ ) {
145✔
472
        new_job = new ScheduledJobQueueInstrument( instrumentation_job, list[ii] );
127✔
473
        list[ii]->add_inst_before(new_job) ;
127✔
474
    }
475

476
    return 0 ;
18✔
477
}
478

479
/**
480
@details
481
-# For all jobs in the queue
482
    -# Create a new ScheduledJobQueueInstrument instance
483
    -# Add the new instrumentation job to the "after" instrumentation job list
484
-# Return 0
485
*/
486
int Trick::ScheduledJobQueue::instrument_after(Trick::JobData * instrumentation_job) {
17✔
487

488
    unsigned int ii ;
489
    ScheduledJobQueueInstrument * new_job ;
490

491
    /* Count the number of non-instrumentation jobs in the current queue. */
492
    for ( ii = 0 ; ii < list_size ; ii++ ) {
140✔
493
        new_job = new ScheduledJobQueueInstrument( instrumentation_job, list[ii] );
123✔
494
        list[ii]->add_inst_after(new_job) ;
123✔
495
    }
496

497
    return 0 ;
17✔
498
}
499

500
/**
501
@details
502
-# For all jobs in the queue
503
    -# Create a new ScheduledJobQueueInstrument instance
504
    -# Add the new instrumentation job to the list
505
-# Return 0
506
*/
507
int Trick::ScheduledJobQueue::instrument_remove(std::string job_name) {
×
508

509
    unsigned int ii ;
510

511
    for ( ii = 0 ; ii < list_size ; ii++ ) {
×
512
        list[ii]->remove_inst(job_name) ;
×
513
    }
514

515
    return 0 ;
×
516
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc