Tuesday, May 29, 2012

boost: new functions for me



1. Links

bind
http://www.boost.org/doc/libs/1_49_0/libs/bind/bind.html




Friday, May 25, 2012

What is the difference between UDP and TCP internet protocols?


1. Links

http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/

Q. Can you explain the difference between UDP and TCP internet protocol (IP) traffic and its usage with an example?
A. Transmission Control Protocol (TCP) and User Datagram Protocol (UDP)is a transportation protocol that is one of the core protocols of the Internet protocol suite. Both TCP and UDP work at transport layer TCP/IP model and both have very different usage.

Difference between TCP and UDP

TCPUDP
Reliability: TCP is connection-oriented protocol. When a file or message send it will get delivered unless connections fails. If connection lost, the server will request the lost part. There is no corruption while transferring a message.Reliability: UDP is connectionless protocol. When you a send a data or message, you don't know if it'll get there, it could get lost on the way. There may be corruption while transferring a message.
Ordered: If you send two messages along a connection, one after the other, you know the first message will get there first. You don't have to worry about data arriving in the wrong order.Ordered: If you send two messages out, you don't know what order they'll arrive in i.e. no ordered
Heavyweight: - when the low level parts of the TCP "stream" arrive in the wrong order, resend requests have to be sent, and all the out of sequence parts have to be put back together, so requires a bit of work to piece together.Lightweight: No ordering of messages, no tracking connections, etc. It's just fire and forget! This means it's a lot quicker, and the network card / OS have to do very little work to translate the data back from the packets.
Streaming: Data is read as a "stream," with nothing distinguishing where one packet ends and another begins. There may be multiple packets per read call.Datagrams: Packets are sent individually and are guaranteed to be whole if they arrive. One packet per one read call.
Examples: World Wide Web (Apache TCP port 80), e-mail (SMTP TCP port 25 Postfix MTA), File Transfer Protocol (FTP port 21) and Secure Shell (OpenSSH port 22) etc.Examples: Domain Name System (DNS UDP port 53), streaming media applications such as IPTV or movies, Voice over IP (VoIP), Trivial File Transfer Protocol (TFTP) and online multiplayer games etc

Further readings

Thursday, May 24, 2012

Windows timer


1. Links

Timers Tutorial
http://www.codeproject.com/Articles/1236/Timers-Tutorial


Queue Timers

The last kind of Windows - supported timers that we are going to read about in this article is queue timers. They were introduced with Windows 2000.
Queue timers are lightweight kernel objects that reside in timer queues. Like most timers, they enable us to specify the callback function to be called when the specified due time arrives. In this case, the operation is performed by a thread in the Windows thread pool.
Here, for the sake of simplicity, we are not going to create our timer queues. Instead, we will put our queue timers into default timer queue, provided by the OS.
First, we need to create a timer and add it to the default timer queue. For this, we'll make a call to:
BOOL CreateTimerQueueTimer(PHANDLE phNewTimer, HANDLE TimerQueue , 
 WAITORTIMERCALLBACK Callback, PVOID Parameter, DWORD DueTime, 
 DWORD Period, ULONG Flags); 

Arguments

  • phNewTimer - Pointer to a handle; this is an out value
  • TimerQueue - Timer queue handle. For the default timer queue, NULL
  • Callback - Pointer to the callback function
  • Parameter - Value passed to the callback function
  • DueTime - Time (milliseconds), before the timer is set to the signaled state for the first time
  • Period - Timer period (milliseconds). If zero, timer is signaled only once
  • Flags - One or more of the next values (table taken from MSDN):
WT_EXECUTEINTIMERTHREAD The callback function is invoked by the timer thread itself. This flag should be used only for short tasks or it could affect other timer operations.
WT_EXECUTEINIOTHREAD The callback function is queued to an I/O worker thread. This flag should be used if the function should be executed in a thread that waits in an alertable state. The callback function is queued as an APC. Be sure to address reentrancy issues if the function performs an alertable wait operation.
WT_EXECUTEINPERSISTENTTHREAD The callback function is queued to a thread that never terminates. This flag should be used only for short tasks or it could affect other timer operations. Note that currently no worker thread is persistent, although no worker thread will terminate if there are any pending I/O requests.
WT_EXECUTELONGFUNCTION Specifies that the callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.
WT_EXECUTEONLYONCE The timer will be set to the signaled state only once.

Return Value

  • Nonzero if the function succeeds
The callback function is really pretty simple:
VOID CALLBACK WaitOrTimerCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired); 

Arguments

  • lpParameter - Pointer to user-defined data
  • TimerOrWaitFired - always TRUE for timer callbacks
To cancel a queue timer, use the function:
BOOL DeleteTimerQueueTimer(HANDLE TimerQueue, HANDLE Timer, HANDLE CompletionEvent); 

Arguments

  • TimerQueue - A handle to the (default) timer queue
  • Timer - A handle to the timer
  • CompletionEvent - A handle to an optional event to be signaled when the function is successful and all callback functions have completed. Can be NULL.

Return Value

  • Nonzero if the function succeeds
The example for queue timers is given below:
void CTimersDlg::OnButtonBegin()
{
 .
 .
 .
    // create the timer

 BOOL success = ::CreateTimerQueueTimer(
  &m_timerHandle,
  NULL,
  TimerProc,
  this,
  0,
  elTime,
  WT_EXECUTEINTIMERTHREAD);
}

void CTimersDlg::OnButtonStop()
{
    // destroy the timer
 DeleteTimerQueueTimer(NULL, m_timerHandle, NULL);
 CloseHandle (m_timerHandle);
}

void CTimersDlg::QueueTimerHandler() // called every elTime milliseconds
{
// do what you want to do, but quickly
 .
 .
 .
}

void CALLBACK TimerProc(void* lpParametar,
                                    BOOLEAN TimerOrWaitFired)
    {
    // This is used only to call QueueTimerHandler
    // Typically, this function is static member of CTimersDlg
    CTimersDlg* obj = (CTimersDlg*) lpParametar;
    obj->QueueTimerHandler();
    } 
As you can see, queue timers are pretty easy to use. I can also add that they are very accurate, and "resource friendly".
As I noted at the beginning of this chapter, queue timers are supported on Windows 2000 and later. If you do not want to support older Windows versions, they are perfect, and should be used instead of multimedia timers.

Conclusion

What's the moral of the whole story?
When you decide that you need a timer in your application, choosing between the different timer variants should not be that hard. Follow these simple rules:
  1. If you want your application to work on every 32 bit Windows platform, you do not need high precision, and the callback operation is fast enough not to disrupt the UI responsiveness, use a standard Win32 timer.
  2. If you want your application to work on every 32 bit Windows platform, and you need high precision, use the multimedia timer.
  3. If you want your application to work on Windows 98/NT4 and later, you need low system overhead, and can afford to block the calling thread, use the waitable timer.
  4. If you want a high-precision, low-overhead, non-blocking timer that will work on Windows 2000 and later, use the queue timer.








// Trying with new implementation

void CALLBACK TimerProc(void* lpParametar, BOOLEAN TimerOrWaitFired){
    // This is used only to call step()
    // Typically, this function is static member of AbstractEngine
    AbstractEngine* obj = (AbstractEngine*) lpParametar;
    obj->step();
}

int AbstractEngine::activate(){
    winACStepsRun = 0;

    if (engineCanBeActivated) {
        if(!modelThreadRunning){
            startModelThread();
            Logger::info("Engine activated, model thread started.");
            if ( router->getTcpServer() ){
                router->getTcpServer()->startServer();
            } else {
                Logger::warning("Cannot start TCP server.");
                return 1;
            }

    BOOL success = ::CreateTimerQueueTimer(
        &m_timerHandle,
        NULL,
        TimerProc,
        this,
        0,
        10,
        WT_EXECUTEINTIMERTHREAD);
        }
    } else {
        Logger::warning("Engine could not be activated.");
        return 2;
    }

    return 0;
}








Wednesday, May 23, 2012

TCP communication with boost


1. Links

A guide to getting started with boost::asio
http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=8







Monday, May 14, 2012

Microsoft Access: VBA & Check NULL fields & ...


1. Links

Examples of expressions that check for null values
http://office.microsoft.com/en-ca/access-help/examples-of-expressions-that-check-for-null-values-HP001099035.aspx

Nz Function
http://office.microsoft.com/en-us/access-help/nz-function-HA001228890.aspx

http://www.techonthenet.com/access/functions/index.php
http://www.techonthenet.com/access/modules/recordset.php

Introduction to Microsoft Access and VBA
http://www.functionx.com/vbaccess/Lesson01.htm

MS Access: Database variable "not defined" error in Access 2003/XP/2000/97
http://www.techonthenet.com/access/questions/db_object.php

2. Details
For access 2007 - 2010, go to Database Tools/Visual Basic
Right click to Modules and select Insert\Module
Edit the code as below example
Save as module name

On the form or query, just call GetStatus() example:
=GetStatus([HistorySWT1];[HistorySWT2];[HistorySWT3])


3. Example


=IIf(IsNull([SWT1History]);"";[SWT1History])

VBA example:

Option Compare Database

Option Explicit


Function GetStatus(sHisSWT1, sHisSWT2, sHisSWT3 As String) As String

    Dim sStatus As String

If IsNull(sHisSWT1) Or IsNull(sHisSWT1) Or IsNull(sHisSWT1) Then
    GetStatus = "++++++++++++"
Else
    If sHisSWT1 <> "" Then
        sStatus = sHisSWT1 + " - "
    End If
   
    If sHisSWT2 <> "" Then
        sStatus = sStatus + sHisSWT2 + " - " ' + sHisSWT3
    End If
   
    sStatus = sHisSWT1 + " - " + sHisSWT2 + " - " + sHisSWT3
   
   
        If sHisSWT3 = "Reopened" Then
            sStatus = "Open"
        Else
            If (sHisSWT2 = "Solved") Or (sHisSWT2 = "Identified, Solved") Then
                sStatus = "Closed"
            Else
                If sHisSWT1 = "Identified" Then
                    sStatus = "Identified"
                Else
                    sStatus = "~"
                End If
            End If
        End If
       
    GetStatus = sStatus
End If

End Function





Friday, May 11, 2012

Calling conventions for functions: __cdecl, __stdcall, __fastcall, WINAPI, etc

1. Links

Calling Conventions Demystified: http://www.codeproject.com/Articles/1388/Calling-Conventions-Demystified


Conclusion
To cut a long story short, we'll outline the main differences between the calling conventions:
  • __cdecl is the default calling convention for C and C++ programs. The advantage of this calling convetion is that it allows functions with a variable number of arguments to be used. The disadvantage is that it creates larger executables.
  • __stdcall is used to call Win32 API functions. It does not allow functions to have a variable number of arguments.
  • __fastcall attempts to put arguments in registers, rather than on the stack, thus making function calls faster.
  • Thiscall calling convention is the default calling convention used by C++ member functions that do not use variable arguments.




Thursday, May 3, 2012

C/C++ thread



1. Mutex

Links
http://thisthread.blogspot.com/2010/05/ipc-with-boost-anonymous-mutex.html

Sample

1. the class SharedMemoryLog manages the concurrent access by the differnt processes, and it would be associated to memory placed in shared memory. Notice that any method is shielded by scoped_lock on the mutex owned by the class.
2. the class ShMemManager is used to manage the shared memory. A parameter in the constructor let us to determine if we want call it to actually create the shared memory - that would be the usage for the master process - or just to read it - for the secondary process.
3. the last line of the ShMemManager constructor associate the sml_ pointer to the SharedMemoryLog class to the shared memory we have just created or accessed. If we are in creation mode, we should actually call the constructor for the SharedMemoryLog asking it to use the shared memory. To do that we use the so called placement new construct "new (addr) SharedMemoryLog" specifying the memory address we should use. Otherwise we simply perform a static cast to the require type.
4. the function called from the master process. It just puts a few lines in the log (slowing down the process with a sleep call), dumps the log, stays in busy wait for the other process to complete, then performs another dump before returning. This busy wait is not very good programming, we should use a condition instead. We'll see how to do that in a next post.
5. the function called by the secondary process. The main diffences to the master is that we call the constructor for the ShMemManager specifying that we want to access shared memory already available; and then we let the master knowing we are done callint the function done() that sets an internal flag. As already said, this is not a very clean way of working, we'll see how to do better using a condition.

The code is based on an example provided by the Boost Library Documentation.


#include <cstdio>
#include <iostream>
 
#include "boost/interprocess/sync/interprocess_mutex.hpp"
#include "boost/interprocess/sync/scoped_lock.hpp"
#include "boost/interprocess/shared_memory_object.hpp"
#include "boost/interprocess/mapped_region.hpp"
#include "boost/thread/thread.hpp"
 
using namespace boost::interprocess;
 
namespace
{
  const char* MY_SHARED = "MySharedMemory";
 
  class SharedMemoryLog // 1.
  {
  private:
    enum { NUM_ITEMS = 10, LINE_SIZE = 100 };
    boost::interprocess::interprocess_mutex mutex_;
 
    char items[NUM_ITEMS][LINE_SIZE];
    int curLine_;
    bool done_;
  public:
    SharedMemoryLog() : curLine_(0), done_(false) {}
 
    void push_line(const char* id, int index)
    {
      scoped_lock<interprocess_mutex> lock(mutex_);
      std::sprintf(items[(curLine_++) % SharedMemoryLog::NUM_ITEMS], "%s_%d", id, index);
      std::cout << "Inserting item " << id << ' ' << index << std::endl;
    }
 
    void dump()
    {
      scoped_lock<interprocess_mutex> lock(mutex_);
      for(int i = 0; i < NUM_ITEMS; ++i)
        std::cout << items[i] << std::endl;
    }
 
    void done()
    {
      scoped_lock<interprocess_mutex> lock(mutex_);
      done_ = true;
    }
 
    bool isDone()
    {
      scoped_lock<interprocess_mutex> lock(mutex_);
      return done_;
    }
  };
 
  class ShMemManager // 2.
  {
  private:
    std::string name_;
    bool create_;
    shared_memory_object shm_;
    mapped_region region_;
    SharedMemoryLog* sml_;
 
    void remove() { shared_memory_object::remove(name_.c_str()); }
  public:
    ShMemManager(const char* name, bool create = true) : name_(name), create_(create)
    {
      if(create_)
      {
        remove();
 
        shared_memory_object shm(create_only, name_.c_str(), read_write);
        shm.truncate(sizeof(SharedMemoryLog));
        shm_.swap(shm);
      }
      else
      {
        shared_memory_object shm(open_only, name_.c_str(), read_write);
        shm_.swap(shm);
      }
 
      mapped_region region(shm_, read_write);
      region_.swap(region);
      void* addr = region_.get_address();
 
      sml_ = create_ ? new (addr) SharedMemoryLog : static_cast<SharedMemoryLog*>(addr);
    }
 
    ~ShMemManager() { remove(); }
 
    SharedMemoryLog* getMemory() { return sml_; }
  };
}
 
void ip07a() // 4.
{
  std::cout << "Starting master process ..." << std::endl;
 
  try
  {
    ShMemManager smm(MY_SHARED);
    SharedMemoryLog* data = smm.getMemory();
 
    for(int i = 0; i < 7; ++i)
    {
      data->push_line("master", i);
      boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
    }
 
    std::cout << "Master dumps data:" << std::endl;
    data->dump();
 
    while(true)
    {
      if(data->isDone())
      {
        std::cout << "Master sees that the other process is done" << std::endl;
        break;
      }
 
      std::cout << "Master waits for the other process" << std::endl;
      boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
    }
 
    std::cout << "Master dumps again the data:" << std::endl;
    data->dump();
  }
  catch(interprocess_exception& ex)
  {
    std::cout << ex.what() << std::endl;
    return;
  }
 
  std::cout << "Master execution completed" << std::endl;
}
 
void ip07b(const char* id) // 5.
{
  std::cout << "Process " << id << " started" << std::endl;
 
  try
  {
    ShMemManager smm(MY_SHARED, false);
    SharedMemoryLog* data = smm.getMemory();
 
    for(int i = 0; i < 7; ++i)
    {
      data->push_line(id, i);
      boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
    }
    data->done();
 
    std::cout << id << " dumps data:" << std::endl;
    data->dump();
  }
  catch(interprocess_exception& ex)
  {
    std::cout << ex.what() << std::endl;
    return;
  }
 
  std::cout << "Process " << id << " done" << std::endl;
}