00001 // $Id: camprofile.cpp 1464 2006-07-18 12:32:26Z gerry $ 00002 /* @@tag:xara-cn@@ DO NOT MODIFY THIS LINE 00003 ================================XARAHEADERSTART=========================== 00004 00005 Xara LX, a vector drawing and manipulation program. 00006 Copyright (C) 1993-2006 Xara Group Ltd. 00007 Copyright on certain contributions may be held in joint with their 00008 respective authors. See AUTHORS file for details. 00009 00010 LICENSE TO USE AND MODIFY SOFTWARE 00011 ---------------------------------- 00012 00013 This file is part of Xara LX. 00014 00015 Xara LX is free software; you can redistribute it and/or modify it 00016 under the terms of the GNU General Public License version 2 as published 00017 by the Free Software Foundation. 00018 00019 Xara LX and its component source files are distributed in the hope 00020 that it will be useful, but WITHOUT ANY WARRANTY; without even the 00021 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 See the GNU General Public License for more details. 00023 00024 You should have received a copy of the GNU General Public License along 00025 with Xara LX (see the file GPL in the root directory of the 00026 distribution); if not, write to the Free Software Foundation, Inc., 51 00027 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00028 00029 00030 ADDITIONAL RIGHTS 00031 ----------------- 00032 00033 Conditional upon your continuing compliance with the GNU General Public 00034 License described above, Xara Group Ltd grants to you certain additional 00035 rights. 00036 00037 The additional rights are to use, modify, and distribute the software 00038 together with the wxWidgets library, the wxXtra library, and the "CDraw" 00039 library and any other such library that any version of Xara LX relased 00040 by Xara Group Ltd requires in order to compile and execute, including 00041 the static linking of that library to XaraLX. In the case of the 00042 "CDraw" library, you may satisfy obligation under the GNU General Public 00043 License to provide source code by providing a binary copy of the library 00044 concerned and a copy of the license accompanying it. 00045 00046 Nothing in this section restricts any of the rights you have under 00047 the GNU General Public License. 00048 00049 00050 SCOPE OF LICENSE 00051 ---------------- 00052 00053 This license applies to this program (XaraLX) and its constituent source 00054 files only, and does not necessarily apply to other Xara products which may 00055 in part share the same code base, and are subject to their own licensing 00056 terms. 00057 00058 This license does not apply to files in the wxXtra directory, which 00059 are built into a separate library, and are subject to the wxWindows 00060 license contained within that directory in the file "WXXTRA-LICENSE". 00061 00062 This license does not apply to the binary libraries (if any) within 00063 the "libs" directory, which are subject to a separate license contained 00064 within that directory in the file "LIBS-LICENSE". 00065 00066 00067 ARRANGEMENTS FOR CONTRIBUTION OF MODIFICATIONS 00068 ---------------------------------------------- 00069 00070 Subject to the terms of the GNU Public License (see above), you are 00071 free to do whatever you like with your modifications. However, you may 00072 (at your option) wish contribute them to Xara's source tree. You can 00073 find details of how to do this at: 00074 http://www.xaraxtreme.org/developers/ 00075 00076 Prior to contributing your modifications, you will need to complete our 00077 contributor agreement. This can be found at: 00078 http://www.xaraxtreme.org/developers/contribute/ 00079 00080 Please note that Xara will not accept modifications which modify any of 00081 the text between the start and end of this header (marked 00082 XARAHEADERSTART and XARAHEADEREND). 00083 00084 00085 MARKS 00086 ----- 00087 00088 Xara, Xara LX, Xara X, Xara X/Xtreme, Xara Xtreme, the Xtreme and Xara 00089 designs are registered or unregistered trademarks, design-marks, and/or 00090 service marks of Xara Group Ltd. All rights in these marks are reserved. 00091 00092 00093 Xara Group Ltd, Gaddesden Place, Hemel Hempstead, HP2 6EX, UK. 00094 http://www.xara.com/ 00095 00096 =================================XARAHEADEREND============================ 00097 */ 00098 00099 00100 #include "camtypes.h" 00101 00102 //#include "camconfig.h" 00103 #include "camprofile.h" 00104 00105 #if WIN32 00106 // include something for GetSytemTimeAsFileTime 00107 #else 00108 #include <sys/time.h> 00109 #include <time.h> 00110 #endif 00111 00112 CC_IMPLEMENT_DYNCREATE(CamProfile, CCObject) 00113 CC_IMPLEMENT_DYNCREATE(CamProfiler, CCObject) 00114 00115 // Declare smart memory handling in Debug builds 00116 #define new CAM_DEBUG_NEW 00117 00118 CamProfile* CamProfile::pHead=NULL; 00119 CamProfile* CamProfile::pTail=NULL; 00120 CamProfile* CamProfile::pCurrent=NULL; 00121 CamProfile* CamProfile::OurHead=NULL; 00122 UINT64 CamProfile::LastOilTime=0; 00123 UINT64 CamProfile::OilTimeArray[CAMPROFILE_NONE]; 00124 BOOL CamProfile::Running=0; 00125 BOOL CamProfile::Inited=0; 00126 00127 /******************************************************************************************** 00128 00129 > CamProfile::CamProfile(CamProfileMode myMode = CAMPROFILE_NONE ) 00130 00131 00132 Author: Alex_Bligh <alex@alex.org.uk> 00133 Created: 24/11/2005 00134 Inputs: - 00135 Outputs: - 00136 Returns: - 00137 Purpose: Default constructor 00138 Errors: - 00139 SeeAlso: - 00140 00141 ********************************************************************************************/ 00142 00143 CamProfile::CamProfile(CamProfileMode myMode) 00144 { 00145 // Set up in isolation 00146 00147 Mode = CAMPROFILE_NONE; 00148 pPrev = NULL; 00149 pNext = NULL; 00150 OilTime = 0; 00151 00152 Zombie = FALSE ; 00153 00154 if (!Running) 00155 { 00156 Zombie = TRUE; 00157 return; 00158 } 00159 00160 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00161 00162 // Add us to the end of the list 00163 if (pTail) 00164 { 00165 pTail->pNext = this; 00166 pPrev = pTail; 00167 } 00168 pTail = this; 00169 00170 if (!pHead) 00171 { 00172 pHead = this; 00173 } 00174 00175 // note we didn't alter pCurrent above, so it's still set to the old one 00176 SetMode(myMode); 00177 00178 } 00179 00180 /******************************************************************************************** 00181 00182 > CamProfile::~CamProfile() 00183 00184 00185 Author: Alex_Bligh <alex@alex.org.uk> 00186 Created: 24/11/2005 00187 Inputs: - 00188 Outputs: - 00189 Returns: - 00190 Purpose: Destructor 00191 Errors: - 00192 SeeAlso: - 00193 00194 ********************************************************************************************/ 00195 00196 CamProfile::~CamProfile() 00197 { 00198 if (Zombie) 00199 { 00200 return; 00201 } 00202 00203 // If it's not a Zombie, but we are still running, we need to do 00204 // list maintenance etc. 00205 00206 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00207 00208 if (pPrev) 00209 { 00210 pPrev->pNext = pNext; 00211 } 00212 else 00213 { 00214 // No previous, we must have been the head 00215 pHead = pNext; 00216 } 00217 00218 if (pNext) 00219 { 00220 pNext->pPrev = pPrev; 00221 } 00222 else 00223 { 00224 // We must have been the tail 00225 pTail = pPrev; 00226 } 00227 00228 // Make sure we don't appear to be in the list still 00229 pNext=NULL; 00230 pPrev=NULL; 00231 00232 // Reawake the previous profiler 00233 if (pTail) 00234 { 00235 // this should wipe us off as pCurrent too. 00236 pTail->SetMode(pTail->Mode); 00237 } 00238 else 00239 { 00240 pCurrent = NULL; 00241 } 00242 00243 ERROR3IF(pCurrent == this, "Somehow current profiler did not get unset"); 00244 } 00245 00246 00247 /******************************************************************************************** 00248 00249 > BOOL CamProfile::Init() 00250 00251 Author: Alex_Bligh <alex@alex.org.uk> 00252 Created: 24/11/2005 00253 Inputs: None 00254 Outputs: None 00255 Returns: TRUE if worked, FALSE if failed (out of memory) 00256 Purpose: Starts up the profiling system 00257 Errors: Returns FALSE on failure. 00258 Scope: Static 00259 00260 ********************************************************************************************/ 00261 00262 00263 BOOL CamProfile::Init() 00264 { 00265 if (Inited) return(FALSE); 00266 00267 for (INT32 i=0; i<CAMPROFILE_NONE; i++) 00268 { 00269 OilTimeArray[i]=0; 00270 } 00271 00272 pHead = NULL; 00273 pTail = NULL; 00274 pCurrent = NULL; 00275 OurHead = new CamProfile; 00276 Running = FALSE; 00277 00278 if (!OurHead) return FALSE; 00279 00280 Inited = TRUE; 00281 00282 // Give the lists a work through 00283 ActivateProfiling (TRUE); 00284 ActivateProfiling (FALSE); 00285 00286 return TRUE; 00287 00288 } 00289 00290 00291 /******************************************************************************************** 00292 00293 > void CamProfile::SetMode(CamProfileMode myMode, BOOL Base=FALSE) 00294 00295 Author: Alex_Bligh <alex@alex.org.uk> 00296 Created: 24/11/2005 00297 Inputs: myMode - the new mode 00298 Base - TRUE to ditch the existing stack of modes 00299 Outputs: None 00300 Returns: TRUE if worked, FALSE if failed (out of memory) 00301 Purpose: Changes the mode of a profiler 00302 Errors: Returns FALSE on failure. 00303 Scope: 00304 00305 This is the heart of the profiling system. We've just been told our timer has changed 00306 from its current state, to myMode. Therefore, if we were profiling before, we attribute 00307 the time passed since that timer started to the relevant array, and mark the old profiler 00308 as being dormant. We then set our own time, and set our start position. 00309 00310 ********************************************************************************************/ 00311 00312 00313 void CamProfile::SetMode(CamProfileMode myMode, BOOL Base) 00314 { 00315 if (Zombie || !Running) 00316 { 00317 return; 00318 } 00319 00320 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00321 00322 UINT64 NewTime; 00323 #if WIN32 00324 // This windows code completely untested by Alex 00325 GetSystemTimeAsFileTime ((LPFILETIME)(&NewTime)); 00326 #else 00327 timeval tv; 00328 gettimeofday(&tv, NULL); 00329 NewTime = (UINT64)(tv.tv_usec)+ ((UINT64)(tv.tv_sec) * 1000000); 00330 #endif 00331 00332 // Mainly for debugging 00333 LastOilTime = NewTime; 00334 00335 // TRACE(_T("CAMPROFILER OilTime is %lld\n"),NewTime); 00336 00337 // If there is a current profiler, stop it. 00338 if (pCurrent && ( pCurrent->Mode != CAMPROFILE_NONE)) 00339 { 00340 // Stop the current profiler running - note this may be us 00341 UINT64 Elapsed = NewTime - pCurrent->OilTime; 00342 OilTimeArray[pCurrent->Mode] += Elapsed; 00343 00344 // TRACE(_T("CAMPROFILER Credit %lld to %d\n"),Elapsed,(INT32)pCurrent->Mode); 00345 00346 pCurrent->OilTime = 0; // So we can detect screw-ups - we'll set it again when we start it 00347 pCurrent=NULL; 00348 } 00349 #if 0 00350 else 00351 { 00352 TRACE(_T("CAMPROFILER AWOOGA1 pCurrent=%llx\n"),pCurrent); 00353 if (pCurrent) 00354 { 00355 TRACE(_T("CAMPROFILER AWOOGA2 Not crediting %llx ticks\n"),NewTime - pCurrent->OilTime); 00356 } 00357 } 00358 #endif 00359 00360 // If the Base flag is set, junk all the others on the list. 00361 if (Base && ( (pTail != this) || (pHead != this))) // don't bother if we're the only one on the list 00362 { 00363 // We are going to junk all the existing profiles except us. Bwahahaha 00364 TRACE(_T("CAMPROFILER Clearing up redudant profiling entries\n")); 00365 00366 // First junk them all 00367 CamProfile * p = pTail; 00368 while (p) 00369 { 00370 CamProfile* pn = p->pPrev; 00371 p->Zombie = TRUE; 00372 p->pPrev = NULL; 00373 p->pNext = NULL; 00374 p = pn; 00375 // sadly they are not ours to delete 00376 } 00377 00378 // Now unjunk us 00379 Zombie = FALSE; 00380 pHead = this; 00381 pTail = this; 00382 } 00383 00384 00385 // Now start us 00386 if (myMode != CAMPROFILE_NONE) 00387 { 00388 OilTime = NewTime; 00389 Mode = myMode; 00390 pCurrent = this; 00391 } 00392 00393 } 00394 00395 /******************************************************************************************** 00396 00397 > static void CamProfile::UpdateOilTimes(); 00398 00399 Author: Alex_Bligh <alex@alex.org.uk> 00400 Created: 24/11/2005 00401 Inputs: None 00402 Outputs: None 00403 Returns: None 00404 Purpose: Updates the current oil times 00405 Errors: Returns FALSE on failure. 00406 Scope: static 00407 00408 This writes the OIL time back into the cumulative time. It should be used before 00409 reading the OilTimesArray to ensure the current profiler hasn't got uncredited 00410 time on. 00411 00412 ********************************************************************************************/ 00413 00414 00415 void CamProfile::UpdateOilTimes() 00416 { 00417 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00418 if (pCurrent && Running && !pCurrent->Zombie) 00419 { 00420 // Resetting the mode is sufficient 00421 pCurrent->SetMode(pCurrent->Mode); 00422 } 00423 } 00424 00425 /******************************************************************************************** 00426 00427 > static void CamProfile::GetTimeString(TCHAR * pTime, UINT32 length); 00428 00429 Author: Alex_Bligh <alex@alex.org.uk> 00430 Created: 24/11/2005 00431 Inputs: length - maximum length of string to be filled in, in CHARACTERS including NULL 00432 Outputs: pTime - filled in with string 00433 Returns: None 00434 Purpose: Returns the current Oil time 00435 Errors: Returns FALSE on failure. 00436 Scope: static 00437 00438 00439 ********************************************************************************************/ 00440 00441 00442 void CamProfile::GetTimeString(TCHAR * pTime, UINT32 length) 00443 { 00444 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00445 UpdateOilTimes(); 00446 if ((length < 26+6) || pCurrent && Running && !pCurrent->Zombie) 00447 { 00448 // Read from LastOilTime 00449 UINT64 Time=LastOilTime; 00450 #if WIN32 00451 // Convert LastOil time to secs since 1 Jan 1970. We don't care about the date, 00452 // we only care about the time, so we pick a roughly correct number of DAYS 00453 // to add. 00454 // That's 369 years, which would have 92 leap years, except for the fact that 00455 // 1700, 1800, 1900 were not leap years. So that's 369 years of 365 days plus 89 00456 // leap year days, or 134,774 days, or 11,644,473,600 seconds 00457 // For the purist, I suppose we might be a few leap seconds out. Yawn. 00458 // Another test (thta's all one line): 00459 // 11perl -e '{use DateTime;$o=DateTime->new(year=>1601,month=>1,day=>1); 00460 // $n=DateTime->new(year=>1970,month=>1,day=>1), 00461 // printf "%d\n", $n->subtract_datetime_absolute($o)->in_units(seconds)}' 00462 // 00463 // 11644473600 00464 // 00465 Time = Time-11644473600LL*10000000LL; 00466 Time = (Time+5)/10; 00467 #endif 00468 // Time is now in microseconds since 1 Jan 1970 00469 UINT64 uSecs = Time % 1000000; 00470 UINT64 Secs = Time / 1000000; 00471 time_t t = Secs; 00472 00473 // Don't use ctime_r as it isn't present on Windows 00474 00475 //Ask wx for a string with the time 00476 wxDateTime TheTime(t); 00477 wxString sTime(TheTime.FormatISOTime()); 00478 00479 // Now camSnprintf this into the string. This turns it into UNICODE if appropriate 00480 camSnprintf (pTime, length, _T("%s.%06d"), sTime.c_str(), uSecs); 00481 } 00482 else camStrncpy(pTime, _T("[UNAVAILABLE]"), length); 00483 pTime[length-1]=0; // ensure string terminated - string copy primatives do funny thing 00484 } 00485 00486 00487 /******************************************************************************************** 00488 00489 > static void CamProfile::AtBase(CamProfileMode myMode=CAMPROFILE_NONE) 00490 00491 Author: Alex_Bligh <alex@alex.org.uk> 00492 Created: 24/11/2005 00493 Inputs: None 00494 Outputs: None 00495 Returns: None 00496 Purpose: Indicates to the profiling system we are at the base of the system 00497 Errors: Returns FALSE on failure. 00498 Scope: Static 00499 00500 This is the heart of the profiling system. We've just been told our timer has changed 00501 from its current state, to myMode. Therefore, if we were profiling before, we attribute 00502 the time passed since that timer started to the relevant array, and mark the old profiler 00503 as being dormant. We then set our own time, and set our start position. 00504 00505 ********************************************************************************************/ 00506 00507 00508 void CamProfile::AtBase(CamProfileMode myMode) 00509 { 00510 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00511 00512 if (!Running) 00513 { 00514 return; 00515 } 00516 00517 if (!pTail) 00518 { 00519 // Note we allocate this, and discard the pointer. That's because it has already 00520 // added itself to the linked list 00521 if (OurHead) delete(OurHead); 00522 OurHead = new CamProfile; 00523 if (!OurHead) return; 00524 } 00525 00526 ERROR3IF(!pTail,"Didn't get a tail pointer"); 00527 if (pTail) 00528 { 00529 pTail->SetMode(myMode, TRUE); 00530 } 00531 } 00532 00533 /******************************************************************************************** 00534 00535 > static BOOL CamProfile::ResetCounters() 00536 00537 Author: Alex_Bligh <alex@alex.org.uk> 00538 Created: 24/11/2005 00539 Inputs: None 00540 Outputs: None 00541 Returns: TRUE if worked, FALSE if failed (out of memory) 00542 Purpose: Resets the profiling counters 00543 Errors: Returns FALSE on failure. 00544 Scope: Static 00545 00546 Reset the counters. DO NOT CALL THIS unless you know what you are doing as it will 00547 mean that anyone with stored counter values is going to get a nasty shock. 00548 00549 ********************************************************************************************/ 00550 00551 00552 BOOL CamProfile::ResetCounters() 00553 { 00554 if (!Running) 00555 { 00556 return TRUE; 00557 } 00558 00559 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00560 00561 CamProfileMode OldMode=CAMPROFILE_NONE; 00562 00563 // Save the old mode of the current operator so we do not credit 00564 // already elapsed time 00565 00566 CamProfile * pActive = pCurrent; 00567 00568 if (pActive) 00569 { 00570 OldMode = pActive->Mode; 00571 pActive->SetMode(CAMPROFILE_NONE); 00572 } 00573 00574 for (INT32 i=0; i<CAMPROFILE_NONE; i++) 00575 { 00576 OilTimeArray[i]=0; 00577 } 00578 00579 if (pActive) 00580 { 00581 pActive->SetMode(OldMode); 00582 } 00583 return TRUE; 00584 } 00585 00586 /******************************************************************************************** 00587 00588 > BOOL CamProfile::ActivateProfiling(BOOL Run = TRUE) 00589 00590 Author: Alex_Bligh <alex@alex.org.uk> 00591 Created: 24/11/2005 00592 Inputs: None 00593 Outputs: None 00594 Returns: TRUE if worked, FALSE if failed (out of memory) 00595 Purpose: Starts up the profiling system 00596 Errors: Returns FALSE on failure. 00597 Scope: Static 00598 00599 This is the heart of the profiling system. We've just been told our timer has changed 00600 from its current state, to myMode. Therefore, if we were profiling before, we attribute 00601 the time passed since that timer started to the relevant array, and mark the old profiler 00602 as being dormant. We then set our own time, and set our start position. 00603 00604 ********************************************************************************************/ 00605 00606 00607 BOOL CamProfile::ActivateProfiling(BOOL Run) 00608 { 00609 // Do nothing if we are already in that state 00610 if (Running == Run) 00611 { 00612 return TRUE; 00613 } 00614 00615 ERROR3IF(!Inited, "Profiling system not yet initialized"); 00616 00617 if (Run) 00618 { 00619 // Ignore old linked list 00620 pHead = NULL; 00621 pTail = NULL; 00622 00623 Running=TRUE; 00624 if (!pHead) 00625 { 00626 // Note we allocate this, and discard the pointer. That's because it has already 00627 // added itself to the linked list 00628 if (OurHead) delete(OurHead); 00629 OurHead = new CamProfile; 00630 if (!OurHead) return FALSE; 00631 } 00632 // We can't wake the zombies up as we don't have a list of them 00633 ResetCounters(); 00634 return TRUE; 00635 } 00636 else 00637 { 00638 if (pCurrent) 00639 { 00640 pCurrent->SetMode(CAMPROFILE_NONE); 00641 } 00642 ResetCounters(); 00643 00644 // Now go through the list removing them all 00645 CamProfile * p = pTail; 00646 while (p) 00647 { 00648 CamProfile* pn = p->pPrev; 00649 p->Zombie = TRUE; 00650 p->pPrev = NULL; 00651 p->pNext = NULL; 00652 p = pn; 00653 // sadly they are not ours to delete 00654 } 00655 pHead = NULL; 00656 pTail = NULL; 00657 00658 if (OurHead) 00659 { 00660 delete (OurHead); 00661 OurHead = NULL; 00662 } 00663 Running = FALSE; 00664 00665 } 00666 return TRUE; 00667 } 00668 00669 /******************************************************************************************** 00670 00671 > CamProfiler::CamProfiler() 00672 00673 00674 Author: Alex_Bligh <alex@alex.org.uk> 00675 Created: 24/11/2005 00676 Inputs: - 00677 Outputs: - 00678 Returns: - 00679 Purpose: Default constructor 00680 Errors: - 00681 SeeAlso: - 00682 00683 ********************************************************************************************/ 00684 00685 CamProfiler::CamProfiler() 00686 { 00687 Reset(); 00688 } 00689 00690 /******************************************************************************************** 00691 00692 > void CamProfiler::Reset() 00693 00694 00695 Author: Alex_Bligh <alex@alex.org.uk> 00696 Created: 24/11/2005 00697 Inputs: - 00698 Outputs: - 00699 Returns: - 00700 Purpose: Resets counters to current 00701 Errors: - 00702 SeeAlso: - 00703 00704 ********************************************************************************************/ 00705 00706 void CamProfiler::Reset() 00707 { 00708 CamProfile::UpdateOilTimes(); 00709 memcpy(OilTimeArray, CamProfile::OilTimeArray, sizeof(OilTimeArray)); 00710 FirstOilTime = CamProfile::LastOilTime; 00711 } 00712 00713 /******************************************************************************************** 00714 00715 > double CamProfiler::Read(double Results[CAMPROFILE_NONE]) 00716 00717 00718 Author: Alex_Bligh <alex@alex.org.uk> 00719 Created: 24/11/2005 00720 Inputs: - 00721 Outputs: Results[CAMPROFILE_NONE] - array of doubles filled with number of seconds elapsed 00722 Returns: total elapsed time 00723 Purpose: Reads counters 00724 Errors: - 00725 SeeAlso: - 00726 00727 Results may be NULL, in which case only the total elapsed time will be returned. 00728 00729 The results in the array should add up to the total returned, but may not if profiling 00730 has been turned off in the mean time. 00731 00732 ********************************************************************************************/ 00733 00734 double CamProfiler::Read(double Results[CAMPROFILE_NONE]) 00735 { 00736 CamProfileMode Mode; 00737 CamProfile::UpdateOilTimes(); 00738 00739 #if WIN32 00740 // This windows code completely untested by Alex 00741 const double factor = 1.0/10000000.0; // Windows uses 100 nanosecond timeslices apparently 00742 #else 00743 const double factor = 1.0/1000000.0; // UNIX counts in microseconds 00744 #endif 00745 00746 INT64 check = 0; 00747 00748 for (Mode = (CamProfileMode)0 ; Mode < CAMPROFILE_NONE ; Mode=(CamProfileMode)((INT32)Mode+1)) 00749 { 00750 // Cast via INT64 to cope with wrap event (ha ha ha). 00751 if (Results) 00752 Results[Mode] = factor * (double)((INT64)(CamProfile::OilTimeArray[Mode] - OilTimeArray[Mode])); 00753 TRACE(_T("CAMPROFILER type %d=%lld\n"),(INT32)Mode,CamProfile::OilTimeArray[Mode] - OilTimeArray[Mode]); 00754 check+=CamProfile::OilTimeArray[Mode] - OilTimeArray[Mode]; 00755 } 00756 00757 INT64 total = (INT64)(CamProfile::LastOilTime - FirstOilTime); 00758 TRACE(_T("CAMPROFILER check=%lld, total=%lld\n"),check,total); 00759 00760 return factor * (double)(total); 00761 }