Boost Bind in C++


Boost.Bind

bind use placehoders concept. bind can have nine argument placeholders.
#include <boost/bind.hpp>

Why use this
 compare to std::bind1st or std::bind2nd can support upto 2 parameters.
 you don't need to use different syntex for pointer or noraml object like std::mem_fun, std::mem_fun_ref.


function binding
void testthree(int i1,int i2, int i3) { std::cout<<i1<<"\t"<<i2<<"\t"<<i3<<"\n"; } int i1=1,i2=2; boost::bind(&testthree,_2,_1,_2)(i1,i2);

result would be : 2 1 2

class member function binding
class test { public: void testmemfun(int i, int j) { std::cout<<i<<"\t"<<j<<"\n"; } }; boost::bind(&test::testmemfun,test(),_1,_2)(param1,param2);

passing in algorithem this pointer or object passed as first parameter.

for_each(vectest.begin(),vectest.end(),boost::bind(&test::testmemfun,_1,param1,param2));
//for pointer container
for_each(vectest.begin(),vectest.end(),std::mem_fun(&test::testmemfun));
//for object container
for_each(vectest.begin(),vectest.end(),boost::bind(&test::testmemfun));  

XML, XSL Transformation in VBA

MS- office2010 does not support document function of xsl stylesheet, so you can't open XML file in Excel.
Microsoft has disabled document function access in stylesheet because of dom security issue.
you need to use referance option from visual basic editor of Excel and select MSXML6.0 for running this macro.
It's step by step process:-
  • Transform xml using xsl.
  • Write transformed data[xhtml or html] in temp file.
  • Open this temp file in new workbook.

Sub VXmlOpen(xmlname As String, xslname As String, strfolder As String) Dim xmlfile As New MSXML2.DOMDocument
' below line is reason to write this macro.
xmlfile.setProperty "AllowDocumentFunction", True xmlfile.async = False xmlfile.Load xmlname Dim xslfile As New MSXML2.DOMDocument xslfile.setProperty "AllowDocumentFunction", True xslfile.async = False xslfile.Load xslname strhtml = xmlfile.transformNode(xslfile) Dim txml As String txml = strfolder + CStr(lcount) + "TempXml.xls" Set xmlfile = Nothing Set xslfile = Nothing On Error GoTo errLbl: Open txml For Output As #1 Print #1, strhtml Close #1 Application.Workbooks.Open txml lcount = lcount + 1 Exit Sub errLbl: MsgBox Err.Description Close #1 End Sub


FileDialog in VBA


Get FileName using Fileopen Dialog box
Function RetrieveFileName() Dim sFileName As String sFileName = Application.GetOpenFilename If sFileName = "False" Then sFileName = "" RetrieveFileName = sFileName End Function

Backtracing in C++/ Linux.

How to backtrace stack symbols for logging.

need -rdynamic option flag for linker to generate export symbol in ELF.
#include <execinfo.h>  
// backtrace header file.
#include <cstdlib> #include <string> #include <cxxabi.h>  
//name mangling header file.
int main() { testbacktrace(); } int testbacktrace() { printf( "[backtracelog]:\n"); void*backtracelog[128]; memset( &backtracelog, 0, sizeof( backtracelog ) ); char** strsymbols; int backtracenptrs = backtrace(backtracelog, 128); printf("number of stackframe %d\n",backtracenptrs);         strsymbols=backtrace_symbols(backtracelog,backtracenptrs); for(int i=0; i<backtracenptrs; ++i){ demangle(strsymbols[i]); } free(strsymbols); backtrace_symbols_fd( backtracelog, backtracenptrs, 1 ); return 0; }
std::string demangle(const char* symbol) { size_t size; int status; char temp[128]; char* demangled;
//first, try to demangle a c++ name
if (1 == sscanf(symbol, "%*[^(]%*[^_]%127[^)+]", temp)) { if (NULL != (demangled = abi::__cxa_demangle(temp, NULL, &size, &status))) { std::string result(demangled); free(demangled); return result; } }
//if that didn't work, try to get a regular c symbol
if (1 == sscanf(symbol, "%127s", temp)) { return temp; }
//if all else fails, just return the symbol
return symbol; }

you can get more details here.                                             

syslog in C++/Linux


syslog to write in system log file.

find log config at following place as per your systems
1./etc/logrotate.d/
2./etc/logrotate.conf
3. /etc/syslog.com

Log stored at following locations.
/var/log/syslog

message managed by syslogd daemon.
passed on socket /dev/log.

#include <syslog.h>
don't delete first parameter of openlog.
always makesure before deleted or out of scope of first parameter use closelog call.
void write2syslog(const std::string & str) { setlogmask (LOG_UPTO (LOG_NOTICE)); openlog ("mydaemon", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); //syslog (LOG_NOTICE, "Program started by User %d", getuid ()); syslog (LOG_INFO, str.c_str()); closelog (); }


Time in C++


Time from C language
1. how to get current time.
2. convert in local time and string format.
3. standard string format time.

#include <ctime> std::string gettime() { static bool btime=false; time_t rawtime; struct tm * timeinfo; char buffer [80]={0}; time ( &rawtime ); timeinfo = localtime ( &rawtime ); btime=!btime; if(btime){ strftime (buffer,80,"Time : %I:%M%:%S p.\n",timeinfo); return std::string(buffer); } return std::string(asctime (timeinfo)); }

Posix Queue De-queuer/Consumer in C++

Last post we read about daemon, which posting message in queue. In this post we write code about consumer who consume those messages. you can use daemon as consumer( look daemon code). we need to use signal processing and mq_notify from posix mqueue. we used old mqueue routines from old post(Posix queue)
Consumer application.

int main() { update_notification(); while(1) pause(); }

Used Code

#include <signal.h>
/* Thread start function */
static void my_sig_handler(union sigval sv) { mqd_t mqid = *((mqd_t *) sv.sival_ptr); std::string strmsg; while(get_message(mqid,strmsg)){ cout<<"Message : "<<strmsg<<endl; } update_notification(mqid);
// re-registor notification
}


void update_notification(mqd_t& mqid) { struct sigevent sigev1;
// For notification
sigev1.sigev_notify = SIGEV_THREAD; sigev1.sigev_notify_function = my_sig_handler; sigev1.sigev_notify_attributes = NULL; sigev1.sigev_value.sival_ptr = &mqid;
/* Arg. to thread func. */
if (mq_notify (mqid, &sigev1) == -1) { if (errno == EBUSY) printf ("Another process has registered for notification.\n"); perror("Error:mq_notify: "); _exit (EXIT_FAILURE); } }


Daemon in C++

Steps for daemon.

  1. fork child process.
  2. if child fork success, exit parent.
  3. umask file permission for child.
  4. set session id or attach with init process.
  5. change current working dirctory.
  6. close standard file descriptors.
  7. start daemon work initilization.
  8. run daemon loop.
  9. handle signals for terminating( we will see next blog).
Sample code daemon loop used Posix Queue toen-queuemessages from old post.
Sample code

void run_daemon() { fork_child(); initchild(); run_daemon(); exit(EXIT_SUCCESS); }

Function used in sample

void fork_child() { pid_t sid;
// fork off the parent process
pid = fork();
// return -1 if failed
if (pid < 0) { exit(EXIT_FAILURE); }
// If we got PID, then exit the parent process.
if (pid > 0) { exit(EXIT_SUCCESS); } } void initchild() { pid_t sid
// set the file mask.
umask(0);
// open log file here for logging.
// set session id for child process.
sid = setsid(); if (sid < 0) { exit(EXIT_FAILURE); }
// change the current working directory
if ((chdir("/")) < 0) { exit(EXIT_FAILURE); }
// close standard file descriptors
close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); }

Main daemon loop

void daemon_loop() {
// daemon-specific initialization
mqd_t mqid; if(open_queue(mqid)){
// daemon loop
while (1) {
// daemon work
send_message(mqid,"This message from daemon",64); sleep(1); // wait } close_queue(mqid); } }

POSIX Message Queue


Posix message queue is way to communicate data between process.
This could use for producer-consumer kind of algorithm.

whenever use this code in daemon, use syslog and strerror(errno) function instead of perror.

Compiling and linking


Header file
#include <mqueue.h> library -lrt use for linking
open a message queue with name.

bool open_queue(mqd_t& mqid,const string& queue_name,unsigned int maxqueue,unsigned int msgsize) {
// First we need to set up the attribute structure
struct mq_attr attr; attr.mq_maxmsg =maxqueue; attr.mq_msgsize = msgsize; attr.mq_flags = 0;
// Open a queue with the attribute structure
mqid = mq_open (queue_name.c_str(), O_RDWR | O_CREAT | O_NONBLOCK,  0666, &attr); if(mqid==(mqd_t)-1){ perror("Error:mq_open: ");  // use syslog and strerror(errno) for daemon return false; } return true; }

closing a message

inline void close_queue(mqd_t& mqid) { mq_close(mqid); }

Send or write message to queue

void send_message(mqd_t& mqid, const std::string& str_msg,unsigned int priority) { if (mq_send (mqid, str_msg.c_str(), str_msg.length(), priority) == -1) perror ("Error:mq_send: ");
// use syslog and strerror(errno) for daemon
}

Get count of message available in queue.

int get_message_count(mqd_t& mqid) { int ret=0 struct mq_attr attr; if(mq_getattr (mqid, &attr)==0){ ret= attr.mq_curmsgs; } else perror("Error:mq_getattr: "); return ret; }

Get the max size of messages.

int get_message_size(mqd_t& mqid) { int ret=0; struct mq_attr attr; if(mq_getattr (mqid, &attr)==0){ ret= attr.mq_msgsize; } else perror("Error:mq_getattr: "); return ret; }

Get a message from message queue.

bool get_message(mqd_t& mqid,const std::string& str_msg) { bool ret=false; int msgsize = get_message_size(mqid); if(msgsize && get_message_count(mqid)){ char* buf= new buf[msgsize+1]; memset(buf,0,msgsize+1); if(mq_receive (mqid, buf, msgsize, &prio) != -1){ str_msg=std::string(buf); ret=true; } delete[] buf; } return ret; }

Be prepared for out-of-memory condition

This is from Effective C++ item 7
How to handle out of memory to get information about your class and overload new operator

use nothrow option with new and check null condion

Widget *pw2 = new (nothrow) Widget; // returns 0 if allocation fails if (pw2 == 0) ... // this test may succeed

use set_new_handler and throw std::bad_alloc exception or abort program.

void noMoreMemory() // globel handle defination { cerr << "Unable to satisfy request for memory\n"; abort();                    // #include <cstdlib> } int main() { set_new_handler(noMoreMemory);    // #include <new> might not need int *pBigDataArray = new int[100000000]; ... }

how to set class level handler


class X { public: static new_handler set_new_handler(new_handler p); static void * operator new(size_t size); private: static new_handler currentHandler; }; new_handler X::currentHandler; // sets currentHandler 0 (i.e., null) by default new_handler X::set_new_handler(new_handler p) { new_handler oldHandler = currentHandler; currentHandler = p; return oldHandler; } void * X::operator new(size_t size) { new_handler globalHandler = // install X's std::set_new_handler(currentHandler); // handler void *memory; try { // attempt memory = ::operator new(size); // allocation } catch (std::bad_alloc&) { // restore std::set_new_handler(globalHandler); // handler; throw; // propagate } // exception std::set_new_handler(globalHandler); // restore handler return memory; } void noMoreMemory();//decl. of function to call if memory allocation for X objects fails X::set_new_handler(noMoreMemory);  // set noMoreMemory as X's new-handling function X *px1 = new X; // if memory allocation fails, call noMoreMemory string *ps = new string; // if memory allocation fails, call the global new-handling function  (if there is one) X::set_new_handler(0); // set the X-specific new-handling function to nothing (i.e., null) X *px2 = new X; // if memory allocation fails, throw an exception immediately. (There is no new-handling function for class X.)

create template base class new handler

template<class T> // "mixin-style" base class class NewHandlerSupport { // for class-specific public: // set_new_handler support static new_handler set_new_handler(new_handler p); static void * operator new(size_t size); private: static new_handler currentHandler; }; template<class T> new_handler NewHandlerSupport<T>::set_new_handler(new_handler p) { new_handler oldHandler = currentHandler; currentHandler = p; return oldHandler; } template<class T> void * NewHandlerSupport<T>::operator new(size_t size) { new_handler globalHandler = std::set_new_handler(currentHandler); void *memory; try memory = ::operator new(size); } catch (std::bad_alloc&) { std::set_new_handler(globalHandler); throw; } std::set_new_handler(globalHandler); return memory; } // this sets each currentHandler to 0 template<class T> new_handler NewHandlerSupport<T>::currentHandler; class X: public NewHandlerSupport<X> { ... // as before, but no declarations for }; // set_new_handler or operator new

best article about this

Counting Objects in C++