1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*
TimeLists.c
AUTHORS:
Allen.Ingling@nyu.edu awi
PLATFORMS:
Only OS X for now.
HISTORY:
1/18/05 awi Wrote it.
DESCRIPTION:
For purposes of instrumenting Screen, maintain times samples in an abstract list type. Internally we use a
linked list. To external functions reading out values, the list appears to be an array.
It is easy to time Screen subfuntions from MATLAB by surrounding them with calls to GetSecs().
It is easy to time OpenGL and other C calls within Screen subfunctions by surrionding them with
PsychGetAdjustedPrecisionTimerSeconds(). However, in this case there is no good way to get the time values back out of
Screen onto MATLAB for analysis. TimeLists are part of the solution. Indivdual Screen subfunctions may use
a time list to store time samples. Those time samples may then be read back into MATLAB using Screen('GetTimeList');
To switch a Screen subfunction into "diagnostic" mode, where it fills a time array, you should create a Screen Preference
setting accessible from MATLAB.
Another way to do the same thing would be to allocate memory within MATLAB and have Screen store values directly
in a MATLAB array. But that has unpleasant drawbacks. Either 1. We let MATLAB build up the list of times by
appending new values to the end. This is bad because MATLAB reallocates memory for the entire list every time it extends
it by one element. 2. We precallocate the list in MATLAB. This is bad because we have to know how long the list needs
to be before we start recording into it.
The close routine which you register with ScriptingGlue, that routine which is executed before the mex file
is flushed, must call ClearTimingArray() to free storage allocated by TimeLists.
TO DO:
No provision is made for multiple simultaneous lists of times. However, it seems better to only maintain one list of
times, and to have a second, parallel list of strings labeling the events which occured at particular times.
*/
#include "Psych.h"
typedef struct _timeArrayElement_{
double timeValue;
struct _timeArrayElement_ *next;
} timeArrayElement;
static timeArrayElement *timeListHead=NULL;
static timeArrayElement *timeListTail=NULL;
static unsigned int numElements=0;
void StoreNowTime(void)
{
double now;
timeArrayElement *newElement;
PsychGetAdjustedPrecisionTimerSeconds(&now);
newElement=(timeArrayElement *)malloc(sizeof(timeArrayElement));
newElement->timeValue=now;
newElement->next=NULL;
if(timeListTail != NULL)
timeListTail->next=newElement;
timeListTail=newElement;
if(timeListHead==NULL)
timeListHead=newElement;
++numElements;
}
void ClearTimingArray(void)
{
timeArrayElement *thisElement, *tempElement;
thisElement=timeListHead;
while(thisElement!=NULL){
if(thisElement->next==NULL){
//end of list. free this element.
free(thisElement);
thisElement=NULL;
timeListHead=NULL;
timeListTail=NULL;
numElements=0;
}else{
//step ahead and free the element behind
tempElement=thisElement;
thisElement=thisElement->next;
free(tempElement);
}
}
}
unsigned int GetNumTimeValues(void)
{
return(numElements);
}
unsigned int GetTimeArraySizeBytes(void)
{
return(numElements * sizeof(double));
}
void CopyTimeArray(double *destination, unsigned int numElements)
{
timeArrayElement *thisElement;
unsigned int i;
thisElement=timeListHead;
for(i=0;i<numElements;i++){
if(thisElement==NULL)
PsychErrorExitMsg(PsychError_internal, "Attempted to copy out more values than are stored in list");
else{
destination[i]=thisElement->timeValue;
thisElement=thisElement->next;
}
}
}
|