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

nasa / trick / 8711508477

16 Apr 2024 07:38PM UTC coverage: 55.9% (-0.05%) from 55.952%
8711508477

Pull #1694

github

web-flow
Merge dfb82b770 into 04822023d
Pull Request #1694: Speed up Trick::ScheduledJobQueue::push

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

13 existing lines in 4 files now uncovered.

12275 of 21959 relevant lines covered (55.9%)

82710.05 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,128✔
20

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

26
}
7,128✔
27

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

38
static bool compare_job_data(const Trick::JobData *a, const Trick::JobData *b) {
54,285✔
39
    {
40
        int ajc = a->job_class;
54,285✔
41
        int bjc = b->job_class;
54,285✔
42
        if (ajc < bjc)
54,285✔
43
            return true;
4,113✔
44
        if (ajc > bjc)
50,172✔
45
            return false;
372✔
46
    }
47
    {
48
        unsigned short ap = a->phase;
49,800✔
49
        unsigned short bp = b->phase;
49,800✔
50
        if (ap < bp)
49,800✔
51
            return true;
16,150✔
52
        if (ap > bp)
33,650✔
53
            return false;
9,173✔
54
    }
55
    {
56
        int asoi = a->sim_object_id;
24,477✔
57
        int bsoi = b->sim_object_id;
24,477✔
58
        if (asoi < bsoi)
24,477✔
59
            return true;
3✔
60
        if (asoi > bsoi)
24,474✔
61
            return false;
15,587✔
62
    }
63
    return a->id < b->id;
8,887✔
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
-# While searching for the correct insertion spot, copy all jobs that precede
72
   the incoming job to the newly allocated queue space followed by the new job.
73
-# Copy jobs that are ordered after the incoming job to the new queue
74
-# Increment the size of the queue.
75
*/
76
int Trick::ScheduledJobQueue::push( JobData * new_job ) {
24,962✔
77

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

91
    new_job->set_handled(true) ;
24,962✔
92

93
    /* Increment the size of the queue */
94
    list_size++ ;
24,962✔
95

96
    return(0) ;
24,962✔
97

98
}
99

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

109
    int save_sim_object_id ;
110
    int ret ;
111

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

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

135
    unsigned int ii , jj ;
136

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

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

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

179
    if ( value < list_size ) {
3,252✔
180
        curr_index = value ;
2,198✔
181
    }
182
    return 0 ;
3,252✔
183
}
184

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

191
    curr_index = 0 ;
1,799,670✔
192
    return(0) ;
1,799,670✔
193
}
194

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

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

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

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

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

247

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

259
    JobData * curr_job ;
260

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

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

297
    JobData * curr_job ;
298
    long long next_call ;
299

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

304
        curr_job = list[curr_index] ;
2,756,497✔
305

306
        if ( curr_job->next_tics == time_tics ) {
2,756,497✔
307

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

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

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

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

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

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

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

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

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

420
int Trick::ScheduledJobQueue::write_sched_queue( FILE * fp ) {
1,803✔
421

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

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

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

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

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

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

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

469
    unsigned int ii ;
470
    ScheduledJobQueueInstrument * new_job ;
471

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

477
    return 0 ;
26✔
478
}
479

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

489
    unsigned int ii ;
490
    ScheduledJobQueueInstrument * new_job ;
491

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

498
    return 0 ;
25✔
499
}
500

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

510
    unsigned int ii ;
511

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

516
    return 0 ;
×
517
}
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

© 2025 Coveralls, Inc