Click here to Skip to main content

Pablo Aliskevicius - Professional Profile

Summary

10,934
Author
4,090
Authority
385
Debator
48
Editor
34
Enquirer
524
Organiser
1,302
Participant
Pablo writes code for a living, in C++, C#, and SQL.
 
To make all that work easier, he uses some C++ libraries: STL, ATL & WTL (to write Windows applications), and code generation.
 
Pablo was born in 1963, got married in 1998, and is the proud father of two wonderful girls.
 
His favorite quote is: "Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, "The Devil's Dictionary", published in several newspapers between 1881 and 1906).
Member since Tuesday, March 25, 2003 (10 years, 1 month)

Contributions

Articles 6 (Legend)
Tech Blogs 0
Messages 171 (Poster)
Q&A Questions 0
Q&A Answers 141
Tips/Tricks 2
Comments 111

Links

Reputation

For more information on Reputation please see the FAQ.

Privileges

Members need to achieve at least one of the given member levels in the given reputation categories in order to perform a given action. For example, to store personal files in your account area you will need to achieve Platinum level in either the Author or Authority category. The "If Owner" column means that owners of an item automatically have the privilege, and the given member types also gain the privilege regardless of their reputation level.

ActionAuthorAuthorityDebatorEditorEnquirerOrganiserParticipantIf OwnerMember Types
Have no restrictions on voting frequencysilversilversilversilverAdmin
Store personal files in your account areaplatinumplatinumSitebuilder, Subeditor, Supporter, Editor, Staff
Have live hyperlinks in your biographybronzebronzebronzebronzebronzebronzesilverSubeditor, Protector, Editor, Staff, Admin
Edit a Question in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Edit an Answer in Q&AsilversilversilversilverYesSubeditor, Protector, Editor, Admin
Delete a Question in Q&AYesSubeditor, Protector, Editor, Admin
Delete an Answer in Q&AYesSubeditor, Protector, Editor, Admin
Report an Articlesilversilversilversilver
Approve/Disapprove a pending ArticlegoldgoldgoldgoldSubeditor, Mentor, Protector, Editor, Staff, Admin
Edit other members' articlesSubeditor, Protector, Editor, Admin
Create an article without requiring moderationplatinumSubeditor, Mentor, Protector, Editor, Staff, Admin
Report a forum messagesilversilverbronzeProtector, Editor, Admin
Create a new tagsilversilversilversilverAdmin
Modify a tagsilversilversilversilverAdmin

Actions with a green tick can be performed by this member.


 
You must Sign In to use this message board.
Search this forum  
GeneralOn global pointers. [modified] Pin
Wednesday, April 4, 2012 7:42 PM by Pablo Aliskevicius
If you see a global pointer (the old fashioned, 'dumb' style), there are three possibilities:
  1. It's a leak. Sometimes, somewhere it's allocated, but it is not always released.
  2. It's dangling. Since it is always is in scope, and it is not always allocated, sometimes it dangles. Even if 98% of the times it is released, it is immediately set to NULL.
  3. Both.
Whenever you open a source file and see a global pointer, exterminate it. Have no mercy. This will save you work and headaches down the road.
Pablo.
 
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).


modified 17 May '12 - 4:57.

 
GeneralThe programmer as an artist Pin
Monday, September 12, 2011 11:09 PM by Pablo Aliskevicius
How do you handle specifications?
There are two approaches I've seen in friends and acquaintances:
  • The coder uses specs as a baking recipe: the code should be a translation of the specs into a language the compiler understands.
  • The programmer is an artist: specs are just another source of inspiration.
This different styles of coding match two different kinds of specification: the artist will be able to use user stories, but will require understanding of the reason why a given functionality is required, and the benefit it is supposed to bring to the people using the software.
This style of specs is (in my opinion) easier to write, and to understand by the layman.

Specs written for the coder, on the contrary, must be painfully detailed. Most QA testers I've met seem to love these, but sooner or later a real customer complains that the program does not do something obvious - and faces the answer 'it works exactly as specified'.

What is your experience?
What kind of specs do you find most useful? How strictly does your code match those specs?
I'd really like to hear.

Pablo.
 
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).

GeneralRe: The programmer as an artist PinmemberAniruddha Loya14 Nov '11 - 21:29 
 
GeneralThere is no such thing as quick and dirty. Pin
Monday, March 30, 2009 9:30 PM by Pablo Aliskevicius
It's either quick and clean, or slow, dirty and painful.
 
Pablo.
 
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).

GeneralRe: There is no such thing as quick and dirty. Pinmember ThatsAlok 18 Jul '11 - 22:57 
GeneralRe: There is no such thing as quick and dirty. PinmemberPablo Aliskevicius19 Jul '11 - 2:39 
GeneralRe: There is no such thing as quick and dirty. Pinmember ThatsAlok 20 Jul '11 - 1:07 
 
GeneralShame on me: a race condition.... Pin
Wednesday, May 28, 2008 8:39 AM by Pablo Aliskevicius
Did you see the thread procedure below?
The pointer pX, which was casted, is shared among threads.
Using it outside the thread loop (after setting the 'I'm really done' event) is a big no-no, since it might have been deleted by the thread manager.
You can protect yourself by defining a scope, like this:
DWORD WINAPI ThreadProc(LPVOID pX)
{
    // Cast passed pointer to what it really is.
    if (pX != NULL)
    {
        X *realPointer = reinterpret_cast<x> pX;
        // Initialize COM
        // Generate message pump
        ::PeekMessage(whatever);
        // Connect to database
        while (!done)
        {
            ::GetMessage(....)
            switch(msg.uMsg)
            {
                case WM_COMMAND: // Cast LPARAM to pointer to a Job, execute that job.
                    realPointer->ExecuteCommand(msg.lParam);
                    break;
                case WM_QUIT:
                    done = true;
                    break;
 
            }
        } // while
        SetEvent(realPointer->reallyDone);
    } // if, scope for casted pointer.
    return 0;
}
 
I'm sad and ashamed to admit - this is from experience.
Happy programming,
Pablo.
 
"Accident: An inevitable occurrence due to the action of immutable natural laws." (Ambrose Bierce, circa 1899).

 
GeneralWhen multithreading is not an option... Pin
Monday, March 19, 2007 10:18 AM by Pablo Aliskevicius

The word 'legacy' means different things to different people. To me, it brings associations of hounted manors...

A few weeks ago, I found myself writing a program (Windows service, listens for events and passes them on) which had to use a legacy DLL while providing decent performance.
The first thing that came to mind was multithreading. It didn't last.

That DLL does not support multithreading: it has lots of global variables, which, if you're old enough, you may remember were deemed 'efficient' by C programmers, since they don't take stack space; in the days of DOS, with 32Kb stack, that was meaningful.
Refactoring the DLL was not an option: lots of work and lots of testing, with the prospect of breaking something, and under an extremely tight budget; and someone else is in charge of maintenance of that DLL.

Then I remembered having seen somewhere threads referred to as 'lightweight processes' (in a book about Windows 95 programming), so I figured, can processes do the task?


Fortunately, the DLL exposes only one function, which performs a rather lengthy batch operation.

The solution was like this:

I wrote an EXE which takes parameters somehow (it reads them from a SQL stored procedure, but the command line or a text file could have been used as well), and passes them to the DLL.
The service manages a process pool, whose maximum size depends on the number of CPUS in the machine.
When an event is detected, it's added to the SQL table which the aforementioned procedure reads from; one of the server processes is selected from the pool; if it's necessary, CreateProcess() is called on the executable (unless it's already running).

It might seem a bit crude, but it gives above-decent performance, the service itself keeps a tiny footprint (it has no code that really 'does' stuff), and any crashes in the legacy DLL (it didn't happen yet, but it might) don't crash the service.

Also, debugging a 'regular process' (single threaded) is easier than debugging a multi-threaded service.

The moral? Sometimes heavyweight is the right weight. As much as I like threads, there are other tools available, and they should not be forgotten.

 

Pablo_A

 
GeneralMore on thread procedures... Pin
Friday, October 13, 2006 3:36 AM by Pablo Aliskevicius
You can find a lot of thread classes and patterns on the Web, but you won't find one which fits all your needs.
That, at least, is what happened to me.
Learnt a lot along the way, though. Here goes some of it.

The main issue is synchronization. There are many shapes and flavors, but the general idea is, the least you serialize access to stuff, the better off you are, both in respect to performance and to the risk of deadlocks.
Then again, there are several kinds of multithreading models.

The simplest one, is the 'shoot and forget' kind: print spooling is an example. You start a process running, and it will be done when it's done. Synchronization here is easy: just don't.

Then there are all the foreman/workers models, when one object (the foreman) lives in a thread, and sends jobs to one or more 'worker' objects, which execute those jobs on separate threads. Here, you can use any kind of mutex (in the broad sense of the term, which includes critical sections and the PostThreadMessage() function), and the appropiate one depends on how long each job will take, and how long the program will be 'on the air'. A Windows service must be more robust than a batch process that runs just for a few minutes.
You avoid deadlocks by locking only the message queue between the foreman and each worker (each worker has one), and for the shortest period of time. Particularly, the worker thread should lock the queue only while it's popping a job, and NOT while it's executing the job. In this design, there are no shared resources among threads but the message queue between a worker and its foreman. The Windows API PostThreadMessage() works like that.
An alternative to this model holds only one message queue for all workers. This one is practical if jobs are rather lengthy: the key question is, how often will a worker wait on the shared message queue while another worker is popping a job.
Some other resources might be shared among threads: think about an error log, if you use a text file for error logging. In that case, you need a OS-level lock (such as a named mutex, in Windows) while you're working with that file. Since errors should be relatively rare, you can get away with this; but, if you're logging, let's say, results, a more robust approach shall be needed. A database, for example.

Designing a multithreaded job

It all begins with a piece of paper, divided in several columns:

  1. User: Represents the user thread.
  2. Foreman: Gets a 'start working' message from the user thread, generates 'jobs' and divides them among the workers (or posts them to a common queue, and each available worker will take them from there). Might report progress to the user's thread.
  3. Workers: This column is usually divided in three: A, B, and Murphy. A and B take turns trying to work, Murphy will try to lock an object whenever it's needed by another thread. As you might have guessed, at design time Murphy is my closest collaborator.

    The workers will usually not report progress, but set some state which can be queried by the foreman.

I've been using threads whenever suitable for a few years now, and haven't met a deadlock yet (I fell into a database deadlock once, but that's a totally different story). Performance is usually satisfactory, despite the cost of thread switches: those can be helped by using a LIFO approach for worker threads, if you've got several of them. Debugging is not that much of an issue, since I unit-test as much as possible (not everything, to be honest), and I keep the bussiness logic apart from the threading code: I also like traces better than breakpoints, anyway.

The bottom line: I've heard people say that multithreading in C++ is hard, error-prone and difficult. Well, those reports, in my humble opinion, are exaggerated.

It's just a tool; use it the right way for the right job, and you'll get the right result.

 

Pablo_A

 
General::PostThreadMessage. Pin
Wednesday, October 11, 2006 8:05 AM by Pablo Aliskevicius
Multi threading is anything but boring.
 
A few days ago, I was asked to improve the performance of a program, which reads a FOX Pro table, generates SQL INSERT commands, and executes them against a database.
 
The way to do it was clear: read in one thread, write on another. To spice things up, since inserting is much slower than reading (all that index updates, you know), three writer threads were matched to the reader.
The writers' thread procedure looked like this (pseudo-code):
 

DWORD WINAPI ThreadProc(LPVOID pX)
{
    // Cast passed pointer to what it really is.
    // Initialize COM
    // Generate message pump
    ::PeekMessage(whatever);
    // Connect to database
    while (!done)
    {
        ::GetMessage(....)
        switch(msg.uMsg)
        {
            case WM_COMMAND: // Cast LPARAM to pointer to a Job, execute that job.
            break;
            case WM_QUIT:
            done = true;
            break;
 
        }
    }
    SetEvent(reallyDone);
    return 0;
}

 
Nice, right?
Tested it with 16K records: runs like the wind, results are fine.
64K records: still OK.
80K records: some start to get lost.
 
I've use ::PostThreadMessage() for quite some time: the caller allocates a Job, posts it to the queue, the worker thread pops it from the queue, executes it, and deletes it. All synchronization tasks are taken care of by the OS, which minimizes thread switches.
 
Well, you always have to read the fine print. And the fine print for ::PostThreadMessage() is that the queue size is 10,000 messages. That's a lot, if you have a few dozen long-running jobs (in the past, for me, that was the usual).
 
So, how could I handle it?
 
My first idea was the use of a 'thermostat'. An integer was interlock-incremented whenever a message was posted, and interlock-decremented whenever a job was executed, thus holding the count of messages in the queue.
 
The manager thread would test the queue size: if longer than 900 messages, it would Sleep for 50 milliseconds: if, after that, there were less than 1000 messages, it would try to post one (in a loop); if, after 5 tries the message was not posted yet, the job would be executed on the calling thread.
 
I didn't like it: whole lot of interlocking going on, and Sleep is by far not my favorite API.
 
Well, the bad news was as expected: performance went down by 30%, but still it was three times faster than the original program.
The good news: 80K records, and none got lost. 150K, and none got lost!
 
So I tried for 400K (the program should be able to send about a million): well, it got stuck after 215K. Playing with the thermostat settings helped a bit, but no cigar.
 
After a couple of hours, I gave up. Added std::queue to the mix, managed synchronization with a critical section (which protected this queue), and performance went back to good. Private bytes and CPU usage were totally flat, up to 400K records.
 
The program was ripe for the QA department.
 
What did I learn?
 
::PostThreadMessage() is a nice tool, but it has some limitations. Its usage: when you have just a few 'big' jobs, and in a program which runs, does its thing and exits. For long-running programs, or programs which send to the worker threads a lot of small jobs, you're better off rolling your own queue.
 
And yet, multithreading, when you know how to do it, can be a great way to make an impression, and to become the star of your company parties.
 

 
Pablo

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   


Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 21 May 2013
Copyright © CodeProject, 1999-2013
All Rights Reserved. Terms of Use
Layout: fixed | fluid