Archive

Posts Tagged ‘Code’

TR1 – How to use array class?

August 17th, 2009 Sarath Comments

The C++ Standard Template Library (STL) provides a framework for processing algorithms on different kind of containers. However, ordinary arrays don’t provide the interface of STL containers (although, they provide the iterator interface of STL containers). As replacement for ordinary arrays, the STL provides class std::vector. However, std::vector<> provides the semantics of dynamic arrays. It manages data to be able to change the number of elements. This results in some overhead in case only arrays with static size are needed.

New new C++ provides a new class called array which is static in usage but able use a standard C++ container. It also provides access to the underlying data. Thus it’s possible to use as raw array pointers. See the sample snippet below to too see how to use array class. A better documentation can be found at boost::array page.

[sourcecode language='cpp']
// using array class
void FooTR1Array()
{
std::tr1::array arr = {1,2,3,4,5};

using namespace std;

cout << "Contents of array " < copy( arr.begin(), arr.end(),
ostream_iterator(std::cout,”\t”));
cout << "Size of array - " << arr.size() < cout << "Front of array - " << arr.front() < cout << "Front of back - " << arr.back() < cout << "Array max Size- " << arr.max_size() < cout << "Array [3] - " << arr[3] < cout << "First element using pointer - " << *arr.data() <

// array swapping - both arrays should have same properties and size
std::tr1::array arrNew = {111,222,333,444,555};

cout << "Contents of array 2" < copy( arrNew.begin(), arrNew.end(),
ostream_iterator(std::cout,”\t”));

// swap array
arr.swap( arrNew );

cout << endl<< "Contents of array 1 after swapping with array 2" < copy( arr.begin(), arr.end(),
ostream_iterator(std::cout,”\t”));

cout << endl<< "Contents of array 2 after swapping with array 1" < copy( arrNew.begin(), arrNew.end(),
ostream_iterator(std::cout,”\t”));
}
[/sourcecode]

Categories: C++, Code, Tips, Visual Studio Tags: , , ,

Windows 7 Ribbon – Part 2 – How handle ribbon control events?

July 2nd, 2009 Sarath Comments

In this installement, let’s see how to handle the events of the ribbon control. I strongly reconmmend you to read the previous post on the basics of ribbon the way it’s being created. This is a continuation of the previous post.

To handle the events, the IUICommandHandler interface is implemented by the application and defines the Command handler methods for framework events.  The following function has to be implemented in the derived class.

Execute
Executes or previews the Commands bound to the Command hand`ler.

UpdateProperty
Sets a property value for a bound Command, for example, setting a Command to enabled or disabled depending on the state of a View.

For each Command in a View(Application.Views in the XML file), the Ribbon framework requires a corresponding Command handler in the host application. A new handler or an existing handler must be bound to the Command through the IUIApplication::OnCreateUICommand notification method.  This method is executed when the UI component is created. It’s possible create new command handler by querying IID_PPV_ARGS intefac. Any number of Commands can be bound to a Command handler.

The Command handler serves two purposes. First, it can update the values of properties for any command to which it is bound, such as setting a command to enabled or disabled. Second, it can execute or preview any commands to which it is bound.

In the previous instalment we’ve seen CRibbonImplementer class. So here we will be modifying the class. We’ll be creating the the handler

Step 1 – Include the generated .h file contains control IDs to the implementation .h/.cpp file of CRibbonImplementer

b1

Step 2 & 3 – Derive ribbon implementer class from IUICommandHandler and add the interface to COM Map

b2

Step 4 – Modify OnCreateUICommand function and add UI Handler on creating the control.

b3

Step 5 -  Add Execute handler to get notification when the button is clicked. This is like the normal message loop of a Win32 message loop system.b4

The final Step (6 ) – It’s necessary to implement IUICommandHandler::UpdateProperty as the base class doesn’t provide any implementations. We can leave this interface as unimplemented.

b5

The full Source code is given below. There’s no change in the other part of source code.

[sourcecode language='cpp']
#include “stdafx.h”
#include
#include
#include
#include
// Step 1: Include menu ribbon resource.h
#include “MenuRibbonRes.h”

class CRibbonImplementer:
public CComObjectRootEx,
public IUIApplication,
// Step 2: derive fromm IUICommandHandler
public IUICommandHandler
{
public:
BEGIN_COM_MAP(CRibbonImplementer)
COM_INTERFACE_ENTRY(IUIApplication)
// Step 3: IUICommandHandler add in teh COM Map
COM_INTERFACE_ENTRY(IUICommandHandler)
END_COM_MAP()

STDMETHOD(OnCreateUICommand)(UINT32 nCmdID, __in UI_COMMANDTYPE typeID, __deref_out IUICommandHandler** ppCommandHandler)
{
// Step 4: IUICommandHandler
// if my button is being created, the handler is created and attached
if (nCmdID == cmdMyButton)
{
return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
}
return E_NOTIMPL;
}

/* Step 5: Implement execute function.
This function will be called on clicking
the controls attached to command handler */
STDMETHODIMP Execute(UINT nCmdID,
UI_EXECUTIONVERB verb,
__in_opt const PROPERTYKEY* key,
__in_opt const PROPVARIANT* ppropvarValue,
__in_opt IUISimplePropertySet* pCommandExecutionProperties)
{
HRESULT hr = S_OK;
switch (verb)
{
case UI_EXECUTIONVERB_EXECUTE:
if (nCmdID == cmdMyButton)
{
MessageBox(NULL, _T( “Clicked on My Button!” ),
_T(”My Button Execute”), MB_OK);
}
break;
}

return hr;

}

// unimplemented methods
// Step 6: Implement Update Property interface as well
STDMETHODIMP UpdateProperty(UINT nCmdID,
__in REFPROPERTYKEY key,
__in_opt const PROPVARIANT* ppropvarCurrentValue,
__out PROPVARIANT* ppropvarNewValue)
{
return E_NOTIMPL;
}

STDMETHOD(OnViewChanged)(UINT32 nViewID, __in UI_VIEWTYPE typeID, __in IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
{
return E_NOTIMPL;
}

STDMETHOD(OnDestroyUICommand)(UINT32 commandId,
__in UI_COMMANDTYPE typeID,
__in_opt IUICommandHandler* pCommandHandler)
{
return E_NOTIMPL;
}

STDMETHODIMP UpdateProperty(UINT nCmdID,
__in REFPROPERTYKEY key,
__in_opt const PROPVARIANT* ppropvarCurrentValue,
__out PROPVARIANT* ppropvarNewValue)
{
return E_NOTIMPL;
}
};
[/sourcecode]

Why CreateProcess commandline parameter should not be read-only memory?

June 5th, 2009 Sarath Comments

In the Book, Windows Via C/C++ Jeffrey Richter mentioned about the peculiarity of command line parameter of CreateProcess function.Normally for most of the Windows API, the input parameters are constant. But for CreateProcess, we’ve to pass the a non const string argument as command line parameter because internally the API modifying the input parameter and the the original data passed will be restored back to its original form, when the API call returns.

Let’s a dig a bit more.
The CreateProcess API takes the following form

[sourcecode language='cpp']
BOOL WINAPI CreateProcess(
__in_opt LPCTSTR lpApplicationName,
__inout_opt LPTSTR lpCommandLine,
__in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes,
__in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes,
__in BOOL bInheritHandles,
__in DWORD dwCreationFlags,
__in_opt LPVOID lpEnvironment,
__in_opt LPCTSTR lpCurrentDirectory,
__in LPSTARTUPINFO lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInformation
);
[/sourcecode]

lpCommandLine parameter of the API is actually specified in LPTSTR which is defined as non-const TCHAR pointer. Effectively we’re not getting anything back from the API but still we’ve to pass a writable memory location. Otherwise there’s a chance to face an access violation as the API tries to modify the passing pointer.

For e.g

[sourcecode language='cpp']
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
CreateProcess( NULL, _T(“NOTEPAD”), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
[/sourcecode]

The above call makes an access violation as the Microsoft C/C++ compiler placing the constant strings in the read only memory. If you use old version of a Microsoft compiler you may not face this access violation as the constant data is stored at read/write memory location.

The best thing we can do is to copy the string to a temporary buffer and pass to the API. We can hope that Microsoft may fix this issue in their future release.

CreateProcess is actually defined as
[sourcecode language='cpp']
#ifdef _UNICODE
#define CreateProcess CreateProcessW
#else
#define CreateProcess CreateProcessA
#endif
[/sourcecode]

If UNICODE is not defined in your project, the API may call ANSI version (CreateProcessA) function which is actually a wrapper function. Inside ANSI version of the most of the APIs, temporary string buffers are defined and the values are converted from ANSI to UNICODE. These string buffers are passed to the UNICODE version of the API which is actually doing the task(remember that Windows is a UNICODE Operating System). So that access violation may not occur for non-unicode applications.

We can solve this problem as follows

[sourcecode language='cpp']
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR cmdline[] = _T( “NOTEPAD”);
CreateProcess( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
[/sourcecode]

Okay we’ve solved the problem. In his recent blog post, Raymond Chen has explained the some more interesting stuff on the same story.

Basically, somebody back in the 1980’s wanted to avoid allocating memory. (Another way of interpreting this is that somebody tried to be a bit too clever.)

The CreateProcess temporarily modifies the string you pass as the lpCommandLine in its attempt to figure out where the program name ends and the command line arguments begin. Now, it could have made a copy of the string and made its temporary modifications to the copy, but hey, if you modify the input string directly, then you save yourself an expensive memory allocation operation. Back in the old days, people worried about avoiding memory allocations, so this class of micro-optimization is the sort of thing people worried about as a matter of course. Of course, nowadays, it seems rather antiquated.

Now, there may also be good technical reasons (as opposed to merely performance considerations) for avoiding allocating memory on the heap. When a program crashes, the just in time debugger is launched with the CreateProcess function, and you don’t want to allocate memory on the heap if the reason the program crashed is that the heap is corrupted. Otherwise, you can get yourself into a recursive crash loop: While trying to launch the debugger, you crash, which means you try to launch the debugger to debug the new crash, which again crashes, and so on. The original authors of the CreateProcess function were careful to avoid allocating memory off the heap, so that in the case the function is being asked to launch the debugger, it won’t get waylaid by a corrupted heap.

Whether these concerns are still valid today I am not sure, but it was those concerns that influenced the original design and therefore the interface.

Categories: C++, Code, Tips, windows Tags: , , , ,

CRT way of renaming a file

May 24th, 2009 Sarath Comments

In one of the previous post I mentioned about How to rename a file using windows API. Many people have asked is there any other option than using MoveFile API for renaming a file. Yes! there’s an alternative you can C-Runtime function rename, _wrenameto rename a file. This code will be portable across platforms as it’s part of standard library function. You can also use _trename , which is a typedef of rename_wrename to make the call compatible with both UNICODE and Non-UNICODE character set

See the sample taken from MSDN itself for renaming a file.
[sourcecode language='cpp']

int _tmain(int argc, _TCHAR* argv[])
{
TCHAR old_filename[] = _T(”CRT_RENAMER.OBJ”), new_filename[] = _T(”CRT_RENAMER.JBO”);

/* Attempt to rename file: */
int result = _trename( old_filename, new_filename );
if( result != 0 )
_tcprintf( _T(”Could not rename ‘%s’\n”), old_filename );
else
_tcprintf( _T(”File ‘%s’ renamed to ‘%s’\n”), old_filename, new_filename );
return 0;
}
[/sourcecode]
–Updated–
2009/05/25 – Made the sample source compatible with both UNICODE and non-UNICODE character set.
2009/05/25 – Updated few typos

Categories: C++, Code, Tips Tags: , , , , ,

Why TRACE0, TRACE1, TRACE2 functions even TRACE macro can have variable arguments?

April 26th, 2009 Sarath Comments

I raised following question in stack overflow some time back.

It’s possible to use TRACE macro as printf like function (variable argument list) . If it supports this facility, then why it’s necessary to have TRACE0, TRACE1 and TRACE2 macros except they’re imposing restrictions on number of arguments. Again, I’d like to know if there are any advantages on restricting number of arguments for TRACE macro.

The viewpoints shared by the community members are.

  • MFC 4 did not have variadic TRACE statements. That was added in a later version. The old-style TRACEn macros are probably there for backward compatibility.
  • The other reason is readability. It isn’t necessary to have the other trace variants (trace1, trace2 etc), but specifying exact number of arguments for a trace function is more readable than infinite number of argument list using TRACE macro

Anyway trace macros are obsolete now. It’s recommended to use ATLTRACE macro instead of TRACE macros. OK here’s quick information on TRACE macros. (See the link above for more info)

To display messages from your program in the debugger Output window, you can use the ATLTRACE macro or the MFC TRACE macro. Like assertions, the trace macros are active only in the Debug version of your program and disappear when compiled in the Release version.

  • TRACE0   Takes a format string (Only) and can be used for simple text messages, which are dumped to afxDump.
  • TRACE1   Takes a format string plus one argument (one variable that is dumped to afxDump).
  • TRACE2   Takes a format string plus two arguments (two variables that are dumped to afxDump).
  • TRACE3   Takes a format string plus three arguments (three variables that are dumped to afxDump)
Categories: C++, Code, MFC Tags: , , ,

A Critical Section is not 100% user mode synchronization object

April 24th, 2009 Sarath Comments

Recently when I was debugging a dead locked program using WinDBG, I accidently met with following stack trace where I expected to see some API calls related to Critical section. Instead it had shown like ‘WaitForSingleObject’ which is solely a kernel mode API. The thread was supposed to be wait state while other thread is owning the critical section shared among threads.

[sourcecode language='cpp']
001bf994 77de9254 76fac244 00000080 00000000 ntdll!KiFastSystemCallRet
001bf998 76fac244 00000080 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
001bfa08 76fac1b2 00000080 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xbe
001bfa1c 009015ab 00000080 ffffffff 00000000 kernel32!WaitForSingleObject+0×12
001bfb04 00901e28 00000001 008679d8 00868b80 DeadLock!wmain+0×6b [c:\users\sarath\documents\visual studio 2008\projects\deadlock\deadlock.cpp @ 21]
001bfb54 00901c6f 001bfb68 76fa4911 7ffd3000 DeadLock!__tmainCRTStartup+0×1a8 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 579]
001bfb5c 76fa4911 7ffd3000 001bfba8 77dce4b6 DeadLock!wmainCRTStartup+0xf [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 399]
001bfb68 77dce4b6 7ffd3000 7736d75f 00000000 kernel32!BaseThreadInitThunk+0xe
001bfba8 77dce489 00901096 7ffd3000 00000000 ntdll!__RtlUserThreadStart+0×23
001bfbc0 00000000 00901096 7ffd3000 00000000 ntdll!_RtlUserThreadStart+0×1b
[/sourcecode]

Why we can see a kernel mode call here? Of course critical sections are faster than kernel mode synchronization objects, as it can avoid user mode to kernel mode transition. But the only condition is that, it shouldn’t any conflicts in acquiring the resource. Critical sections are not purely user-mode synchronization objects. If a thread tries to acquire a critical section and if the object is owned by another thread, then it’s necessary to put the thread in wait mode. To make a thread into wait state, it’s necessary to have a transition from user mode to kernel mode. Of course the critical sections are fast, if there are no contentions. If a contention occurred, then it will be using kernel mode objects to make the corresponding thread in wait state.

Here’s a short note on user mode and kernel mode

1. Kernel Mode

In Kernel mode, the executing code has complete and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system. Crashes in kernel mode are catastrophic; they will halt the entire PC. Various drivers and operating system services are under kernel mode.

2. User Mode

In User mode, the executing code has no ability to directly access hardware or reference memory. Code running in user mode must delegate to system APIs to access hardware or memory. The, crashes in user mode are always recoverable as most of the system calls are executed via safe APIs. Most of the code running on your computer will execute in user mode.

How to programmatically detect if recycle bin empty?

April 20th, 2009 Sarath Comments

In this blog post, I’m talking about, how to detect if recycle bin is empty or not. Also the code snippet allow you to get total count of the items there in the recycle bin.

The contents of Recycle bin appears be in a single folder while it remains in one or more than one of your physical hard drives. You can se the percentage of allocation for each drive in the recycle bin property page as we’re seeing below.

image

The snippet mainly using two functions

SHQueryRecycleBin – Retrieves the size of the Recycle Bin and the number of items in it, for a specified drive.

GetLogicalDriveStrings – helps to retrieve the strings that specify valid drives in the system.

Calling GetLogicalDriveStrings with NULL values will return how many characters need to be passed to fill the data. The return string doesn’t include terminating null character and also in the end the function will put additional null character to specify the end of the data. So we’ve to add 2 characters extra to number of characters to be allocated. The retrieved drive names can be used as input for SHQueryRecyleBin function. If you pass NULL it will give total count of the items in the recyle bin. But it’s adviced not use in that way. See teh documentation for more information. See the sample snippet below


[sourcecode language='cpp']
#include
#include
#include

using namespace std;

bool IsRecycleBinEmpty( DWORDLONG& dwCount )
{
bool bRet = false;

dwCount = 0;

DWORD dwSize = GetLogicalDriveStrings(0, NULL);

// dwSize + 2 null chars
dwSize += 2;

LPTSTR pszDrives = (LPTSTR)malloc((dwSize + 2) * sizeof (TCHAR));

if( NULL != pszDrives )
{
LPTSTR pstr = pszDrives;
SHQUERYRBINFO stInfo;

GetLogicalDriveStrings((dwSize) * sizeof (TCHAR),pszDrives);

while ( _T(”) != *pstr )
{
ZeroMemory (&stInfo, sizeof (stInfo));
stInfo.cbSize = sizeof (stInfo);
HRESULT hr = SHQueryRecycleBin (pstr, &stInfo);
if( SUCCEEDED (hr) && stInfo.i64NumItems)
{
dwCount += stInfo.i64NumItems;
}
pstr += _tcslen(pstr) + sizeof (TCHAR);
}
free( pszDrives );
}
return dwCount ? true : false;
}

int _tmain(int argc, _TCHAR* argv[])
{
DWORDLONG dwCount = 0;
if( IsRecycleBinEmpty( dwCount ))
{
cout << “Recycle bin contains ” << dwCount << “items”;
}
else
{
cout << “Recyle Bin is empty”;
}

return 0;
}
[/sourcecode]

Categories: C++, Code, Tips Tags: , , , ,

How to programmatically turn on/off your monitor

April 3rd, 2009 Sarath Comments

Powerbutton

Recently I saw an interesting question in Stackoverflow forum on programatically turn on/off monitor. Do you want to turn off your  monitor programmatically? It’s not a secret in windows. It’s simple as sending a message

You can send a WM_SYSCOMMAND message with SC_MONITORPOWER and state requried as message parameters. See the function below

[sourcecode language='cpp']
const int MONITOR_ON = -1;
const int MONITOR_OFF = 2;
const int MONITOR_STANDBY = 1;
void SetMonitorPowerState( HWND hWnd, const int state )
{
::SendMessage( hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, state );
}
[/sourcecode]

You can pass your own window as parameter or replace parameter with HWND_BROADCAST to send this message to all top level windows. Alternately you can use GetDesktopWindow() as well. Anyway I am totally unable to distiguish between off and standby while we do it programatically. You can turn on the monitor by mouse movement or keypress. [BTW, the image displayed above is designed myself some time back with the help of a tutorial available in YouTube. (Sorry I missed the link)]
See few links on same topic
Turn off your monitor via code (C#)
Monitor Management

Categories: C++, Tips Tags: , , ,

Cascade errors can happen on forcefully closing handles

March 21st, 2009 Sarath Comments

In his recent Windows Confidential article Win32 and Shell Guru Raymond Chen talking about the caveats of forcefully closing the handles.

In many situations as a windows user  you will definitely faced “File is being used by another process” error when you try to delete or access a file. As a solution for our impatience or to kill the dominance of other process you may forcefully close the file handles. Here are many utilities to close the files being used by foreign application. Tools like Process Explorer allows users to forcefully close any handles opened by any process in the system.

The issues are many

If the the handle is closed earlier by another application, when the original owner will get invalid handle error when it tries to close the corresponding handle.

The invalid handle error may come again if the application uses the handle again. Things may even worse, if the handle value is reused by operating system when the user tries to open another files. As far as the application concerned it got a valid handle value and it’s supposed to point the first file it has opened, in fact the first handle pointer actually points to second file. This may lead data corruption by writing the data intended for the first file is actually written to another file.

Now first and second file handles are actually pointing to the second file and as per the programming logic, if the first file handle is closed, it’s actually closing the second file and you’ve created the same situation which happened to the file earlier. The second file handle got invalid and this can lead to cascaded error.

In the above condition , the error happened when you opened a new file, but what’ if a it’s another kernel object like a mutex, by closing the handle, the mutex handle become invalid and by losing the synchronization, it may lead again for data corruption.

He also explain data corruption issues with search index when forcefully closing handles. Please see the original technet article to know issues with force-handle-close.

Process & Thread Priorities – 101

March 4th, 2009 Sarath Comments

Recently my friend Nibu has blogged about controlling process priority at run time. On seeing that I feel like to write on the basics of thread and process priorities. Of course veterans of Windows programming will not be able make anything better out of this post.

Each process in the system has assigned a certain level of priority when it’s created. Most of the programs are running in the system having normal priority. Some special programs like task manager will be having “Real-Time” priority level. This means, those programs are having higher chance to get the CPU allocated. There are different classes defined to specify the process priority.

Priority class Symbolic Identifier Description
Real-Time REAL_TIME_PRIORITY_CLASS Used to handle time critical tasks. Threads in this process can pre-empts operating system tasks. So carefully use this priority class.
High HIGH_PRIORITY_CLASS High response to the events. E.g Task manager application
Above Normal ABOVE_NORMAL_PRIORITY_CLASS Slightly above normal priority
Below Normal BELOW_NORMAL_PRIORITY_CLASS Below normal priority
Idle IDLE_PRIORITY_CLASS Threads in this process scheduled when the system is idle. Used by screensavers, indexing services etc.

The priority for a process can be specified when it’s created using CreateProcess API. If nothing specified, the process will run under normal priority.

It’s possible to modify the priority of a Process at run-time using SetPriorityClass API. The function takes following form

[sourcecode language='cpp']
BOOL WINAPI SetPriorityClass( __in HANDLE hProcess, __in DWORD dwPriorityClass );
[/sourcecode]

It’s possible to specify any process handle to modify the thread priority class of corresponding process, provided you have a valid handle and permission to modify the process priority. To modify the priority of your own process can be done in the following way

[sourcecode language='cpp']
SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS);
[/sourcecode]

You can get the current priority of a process by using GetPriorityClass function.

[sourcecode language='cpp']
DWORD WINAPI GetPriorityClass( __in HANDLE hProcess );
[/sourcecode]

OK that’s about Process Priority. Here comes about Thread Priority level. Process and thread priority levels are different and related. As specified above the threads are also having time-critical, high, above normal, below normal and idle priorities. The symbolic names are namely THREAD_PRIORITY_TIME_CRITICAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_IDLE

You can specify a thread’s priority by calling SetThreadPriority Function

[sourcecode language='cpp']
BOOL WINAPI SetThreadPriority( __in HANDLE hThread, __in int nPriority );
[/sourcecode]

Note that you can’t set the the thread priority when you’re creating a thread using CreateThread API. Also, windows doesn’t provide no function to get a thread’s priority because operating system may dynamically boost thread’s priority at special situations (e.g keyboard inputs).

Relative priority of threads

Even we’ve different level of priorities for threads; it’s still related to priority of the running process. The actual range of priorities is 0-31. None of the time-critical threads in a normal priority process can attain priority level 31. The operating system maps the thread based on the process’s priority. For example a process having priority class high can attain a maximum thread priority of 15 even we set the thread priority to time critical. While a thread in a process having real-time priority can gain thread priority level 31.

Developers should not work with numerical values of priority, instead use priority class symbolic names to achieve the desired priority because the range process priorities and other related specification can be changed in the future releases of the operating systems.

As a last point. Thread and process priority should not make you confused. Actually the threads in a process doing the real work and process is actually inert but it providing context for the execution.

Categories: Code, Tips Tags: , ,