Fabio Galuppo's profileThe House of Software En...PhotosBlogListsMore Tools Help

Fabio Galuppo

Occupation
Location
Interests
Ignore my interests for a moment. I'm not a nerd or a geeky... I'm a rock'n'roll guy!!!

Titles

Graduation

Bachelor of Computer Science (BCS)

Certification

My MVP Profile

Microsoft Certified Trainer (MCT) - MCT 2008

Microsoft Certified Technology Specialist (MCTS) - Distributed Applications with C++/CLI

Microsoft Certified Solution Developer (MCSD) for .NET

Microsoft Certified Solution Developer (MCSD) for VS 6

Microsoft Certified Application Developer (MCAD)

Microsoft Certified Professional (MCP)

Microsoft Most Valuable Professional 2008 (MVP) for VC++

My MVP Profile at Microsoft MVP Site

Member of

IGDA

ACM

Reference

Fabio Galuppo on Live

Fabio Galuppo on Google

Fabio Galuppo on Yahoo

View Fabio Galuppo's profile on LinkedIn

Contact me

Visit the old house

The House of Software Engineer

The new house is here. The old is there: http://fabiogaluppo.blogspot.com/

About Me

Fabio Galuppo is a software development consultant in São Paulo, SP, Brazil.
He can be contacted to services with C++, C++/CLI, C#, F#, Concurrent and System Programming on Microsoft Platforms (Windows OSes, Windows Mobile OSes, XBox 360).
June 10

Combination Tree

 
This sample generates a set of combined numbers. These numbers are grouped inside a tree structure, which I called combination tree. 
It was built with Visual C++ 2010, using C++0x features (TR1 and lambdas).
 
#include <array>
using std::array
;
using
std::get;

#include
<memory>
using
std::shared_ptr;
 
#include <algorithm>
using
std::for_each;
using
std::transform;

#include
<string>
using
std::string;

#include
<list>
using
std::list;

#include
<iostream>
using
std::cout;
using
std::endl;

template
<typename T, size_t N>

struct
Leaf
{
  typedef shared_ptr<Leaf<T, N>
> LeafType;
  typedef shared_ptr<array<LeafType, N>
> LeavesType;
 
  explicit Leaf(const T& value) : Value(value){}

  LeavesType Leaves;

  T Value;
};

template
<typename T, size_t N>
struct
CombinationTree
{
  typedef typename Leaf<T, N>
::LeavesType LeavesType;
  typedef typename Leaf<T, N>
::LeafType LeafType;

  explicit
CombinationTree() : Root_(make_Leaves()){}

  void add( array<T, N>
& value )
  {
    if( get<0>(*Root_) ) assign_Leaves( Root_, value ); else
assign_Values( Root_, value );
  }

  const LeavesType& get_Root() const { return
Root_; }

private
:
  LeafType make_Leaf(
const T& v ) const { return LeafType( new Leaf<T, N>
(v) ); }
  LeavesType make_Leaves()
const { return LeavesType( new array<LeafType, N>
); }

  void add_Leaf(LeafType& leaf, array<T, N>
& value)
  {
    auto
& leaves = leaf->Leaves;
    if
( leaves.get() )
    {
      assign_Leaves( leaves, value );
      return
;
    }
    leaves = LeavesType(
new array<LeafType, N>
);
    assign_Values( leaves, value );
  }

  void assign_Leaves(LeavesType& leaves, array<T, N>
& value)
  {
    for_each( leaves->begin(), leaves->end(), [
this
, &value](LeafType& l){ add_Leaf(l, value); } );
  }

  void assign_Values(LeavesType& leaves, array<T, N>& value)
const
  {
    transform( value.begin(), value.end(), leaves->begin(), [
this](const T& v){ return
make_Leaf(v); } );
  }

private

  LeavesType Root_;
};

template
<size_t N>
struct
NaiveDumpCombination
{
  const list<string> operator()( const CombinationTree<string, N>
& tree )
  {
    auto
leaves = tree.get_Root();
    list
<string>
combinations;
    for_each
   
      leaves->begin(), leaves->end(), 
      [
this, &combinations](shared_ptr<Leaf<string, N>
> l){ GetCombinations( l, l->Value, combinations ); } 
    );
    return
combinations;
  }

private
:
  void GetCombinations( const shared_ptr<Leaf<string, N>>& leaf, string s, list<string>
& combinations )
  {
    if
( !leaf )
      return
;

    auto
& leaves = leaf->Leaves;

    if
(!leaves)
    {
      combinations.push_back( s );
      return
;
    }

    for_each
   
      leaves->begin(), leaves->end(), 
      [
this, s, &combinations](shared_ptr<Leaf<string, N>
> l)
     
        GetCombinations( l, s +
" "
+ l->Value, combinations );
      }
    );
  }
};

int main()
{
  //combinations with repetition
 
NaiveDumpCombination<5> dump;
  CombinationTree<string, 5> tree;
  array<string, 5> a = { "1", "2", "3", "4", "5" }; 
  tree.add(a);
  tree.add(a);
  tree.add(a);
  tree.add(a);
  tree.add(a);
  const auto
& combination = dump( tree );
  for_each( combination.begin(), combination.end(), [](string s){ cout << s << endl; } );
}
May 08

Comma Quibbling Puzzle

Some days ago (almost one month ago), Eric Lippert post a cool puzzle.
I did some solutions, to be exact, one in C++ and 2 in C#. So, today I had time to compile them here...
 
C++ Solution:
 
#include
<algorithm>
#include
<string>
#include
<sstream>
#include
<iostream>
#include
<vector>
#include
<iterator>

using
namespace std;

namespace
Solution
{
  template< class Elem, class TString = basic_string<Elem>, class TSequenceContainter = vector<TString> >
  class GetSequence
  {
    TString Open_, Close_, Separator_, Separator_End_; 
    int min( int lVal, int rVal ){ return lVal < rVal ? lVal : rVal; }
  public:
    GetSequence(TString open, TString close, TString separator, TString separator_end) :
    Open_(open), Close_(close), Separator_(separator), Separator_End_(separator_end){}
    TString get(const TSequenceContainter& items)
    {
      TSequenceContainter::size_type itemsCount = items.size();
      typedef ostream_iterator<TString, Elem> iter;
      basic_stringstream<Elem> ss;
      ss << Open_;
      copy( items.begin(), items.end() - min(2, itemsCount), iter( ss, Separator_.c_str() ) );
      copy( items.end() - min(2, itemsCount), items.end() - min(1, itemsCount), iter( ss, Separator_End_.c_str() ) );
      copy( items.end() - min(1, itemsCount), items.end(), iter( ss ) );
      ss << Close_;
      return ss.str();
    }
  };

  GetSequence<char> seq_ASCII(){ return GetSequence<char>("{", "}", ", ", " and "); }
  GetSequence<wchar_t> seq_Unicode(){ return GetSequence<wchar_t>(L"{", L"}", L", ", L" and "); }
}

int
main()
{
  vector<string> x;
  x.push_back("A");
  x.push_back("B");
  x.push_back("C");
  x.push_back("D");

  cout << Solution::seq_ASCII().get( x ) << "\n";

  vector<string> y;
  y.push_back("A");
  y.push_back("B");

  cout << Solution::seq_ASCII().get( y ) << "\n";

  vector<string> z;
  z.push_back("A");

  cout << Solution::seq_ASCII().get( z ) << "\n";
  vector<string> w;

  cout << Solution::seq_ASCII().get( w ) << "\n";
  vector<wstring> ux;
  ux.push_back(L"A");
  ux.push_back(L"B");
  ux.push_back(L"C");
  ux.push_back(L"D");

  wcout << Solution::seq_Unicode().get( ux ) << L"\n";

  vector<wstring> uy;
  uy.push_back(L"A");
  uy.push_back(L"B");

  wcout << Solution::seq_Unicode().get( uy ) << L"\n";
  vector<wstring> uz;
  uz.push_back(L"A");

  wcout << Solution::seq_Unicode().get( uz ) << L"\n";
  vector<wstring> uw;
  wcout << Solution::seq_Unicode().get( uw ) << L"\n";
}
 
C# Solutions:
 
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;

static
class Solution
{
  static StringBuilder Append(this StringBuilder sb, string one, string two) { return sb.Append(one).Append(two); }
  static string Next(this IEnumerator<string> enumerator) { enumerator.MoveNext(); return enumerator.Current; }
  public static string GetSequence(IEnumerable<string> items)
  {
    const string OPEN = "{", CLOSE = "}";

    //(1) If the sequence is empty then the resulting string is "{}"
    if (null == items) 
      return OPEN + CLOSE;

    int itemsCount = items.Count();
    switch (itemsCount)
    {
      //(1) If the sequence is empty then the resulting string is "{}"
      case 0:
        return OPEN + CLOSE;
      //(2) If the sequence is a single item "ABC" then the resulting string is "{ABC}"
      case 1:
        return OPEN + items.First() + CLOSE;
      //(3) If the sequence is the two item sequence "ABC", "DEF" then the resulting string is "{ABC and DEF}".
      //(4) If the sequence has more than two items, say, "ABC", "DEF", "G", "H" then the resulting string is "{ABC, DEF, G and H}". (Note: no Oxford comma!)
      default:
        const int COUNTDOWN = 2, ESTIMATED_STRING_LENGTH = 4;
        const string SEPARATOR = ",", SEPARATOR_END = "and";
        var sb = new StringBuilder(OPEN, ESTIMATED_STRING_LENGTH * itemsCount);
        var enumerator = items.GetEnumerator();
        while (COUNTDOWN < itemsCount--) 
          sb.Append(enumerator.Next(), SEPARATOR).Append(" ");
        return sb.Append(enumerator.Next(), " ").Append(SEPARATOR_END, " ").Append(enumerator.Next(), CLOSE).ToString();
    }
  }
}

static
class Solution2
{
  static string Match(this IEnumerable<string> items, params Func<string>[] funcs)
  {
    return funcs[null == items ? 0 : Math.Min(items.Count(), funcs.Length - 1)]();
  }
  
  public static string GetSequence(IEnumerable<string> items)
  {
    return items.Match
    (
      () => { return "{}"; },
      () => { return "{" + items.First() + "}"; },
      () => 
      {
        int count = items.Count() - 2;
        var sb = new StringBuilder("{");
        foreach (var item in items.Take(count))
          sb.Append(item).Append(", ");
        var last = items.Skip(count).ToArray();
        sb.Append(last[0]).Append(" and ").Append(last[1]);
        return sb.Append("}").ToString(); 
      }
    );
  }
}

class
TestProgram
{
  static void Main()
  {
    Action<string> print = Console.WriteLine;
    print( Solution.GetSequence(new string[] { "A", "B", "C", "D" }) );
    print( Solution.GetSequence(new string[] { "A", "B" }) );
    print( Solution.GetSequence(new string[] { "A" }) );
    print( Solution.GetSequence(new string[] {}) );
    print( Solution.GetSequence(null) );

    print(new string('-',20));

    print(Solution2.GetSequence(new string[] { "A", "B", "C", "D" }));
    print(Solution2.GetSequence(new string[] { "A", "B" }));
    print(Solution2.GetSequence(new string[] { "A" }));
    print(Solution2.GetSequence(new string[] { }));
    print(Solution.GetSequence(null));
  }
}
March 09

The Anagram problem (and a sequential solution)

 
This is a sequential solution using C++ of anagram problem pointed out by Eric Lippert's Fabulous Adventures In Coding 
The solution itself is multi-paradigm and platform independent (except in the case of StopWatch which is Windows specific, but could be easily ported).
The file used as dictionary to test is an adapted version of twl06.txt (is the same file only with the words, without the numbers and space). This file could be searched by your preferred search engine.
 
#include
<iostream>
#include
<fstream>
#include
<vector>
#include
<set>
#include
<algorithm>
#include
<iterator>
#include
<functional>
#include
<cstring>
#include
<string>

using
namespace std;

#define
WIN32_LEAN_AND_MEAN

#include
<windows.h>

string Canonicalize( const string& str_value )
{
  string canonicalizedValue( str_value );
  sort( canonicalizedValue.begin(), canonicalizedValue.end() );
  return canonicalizedValue;
}

void
RecursiveReplace( const string& value, set<string>& canonicalizedValues )
{
  string::size_type idx( value.find_first_of( '?' ) );
  if( idx == string::npos )
  {
    canonicalizedValues.insert( Canonicalize( value ) );
    return;
  }
  string value_( value );
  for(char ch = 0x41; ch <= 0x5A; ++ch)
  { 
    value_[ idx ] = ch;
    RecursiveReplace( value_, canonicalizedValues );
  }
}

struct
CanonicalizedValues
{
  CanonicalizedValues( const string& value ) : OriginalValue_( value )
  {
    RecursiveReplace( value, CanonicalizedValues_ );
  }

const set<string>& GetValues() const
{
  return CanonicalizedValues_;
}

const string& GetOriginalValue() const
{
  return OriginalValue_;
}

private
:
  set<string> CanonicalizedValues_;
  string OriginalValue_;
};

struct
FindMatches
{
  FindMatches( const CanonicalizedValues& canonicalizedValues, vector<string>& result )
    : CanonicalizedValues_( canonicalizedValues ),
      Result_( result ),
      WordLength_( canonicalizedValues.GetOriginalValue().length() )
  {
  }

  void operator()( const char* line )
  {
    if( WordLength_ == strlen(line) )
    {
      const set<string>& values( CanonicalizedValues_.GetValues() );
      const string canonicalizedValue( Canonicalize( line ) );
      if( values.end() != find( values.begin(), values.end(), canonicalizedValue ) )
      {
        Result_.push_back( line );
      }
  }
}

private
:
  const CanonicalizedValues& CanonicalizedValues_;
  vector<string>& Result_;
  size_t WordLength_;
};

template
<class Function>
void
ReadLines( const char* filename, Function _Func )
{
  const int MAX_LINE_SIZE = 30;
  char line[MAX_LINE_SIZE];

  ifstream file( filename );

  while( file.getline( line, MAX_LINE_SIZE, '\n' ) )
    _Func( line );

  file.close();
}

struct
StopWatch
{
  StopWatch()
  {
    ::QueryPerformanceFrequency( &Freq_ );
  }

  void Start()
  {
    ::QueryPerformanceCounter( &Start_ );
  }

  void End()
  {
    ::QueryPerformanceCounter( &End_ );
    End_.QuadPart -= Start_.QuadPart;
  }

  __int64 ElapsedTicks()
  {
    return End_.QuadPart;
  }

  double ElapsedTime()
  {
    return static_cast<double>(ElapsedTicks()) / Freq_.QuadPart;
  }

private
:
LARGE_INTEGER Freq_, Start_, End_;
};

int
main()
{
  vector<string> result;
  StopWatch sw;

  sw.Start();

  //CanonicalizedValues values( "AALNSTI?" );
  CanonicalizedValues values( "A????" );
  //CanonicalizedValues values( "AALNST?" );

  ReadLines
  (
    "C:\\Users\\Fabio Galuppo\\Documents\\twl06_adapted.txt",
    FindMatches
    (
      values,
      result
    )
  );

  sw.End();

  copy( result.begin(), result.end(), ostream_iterator<string>( cout, "\n" ) );

  cout << "Count = " << result.size() << "\n" << "Elapsed Time (s) = " << sw.ElapsedTime() << "\n" << "Elapsed Ticks = " << sw.ElapsedTicks() << "\n";
}

 
Next time, I'll (hope to) improve the sample to reading (applying lambdas and others C++0x features) and performance (using concurrency features - probably a boost threads approach and PPL approach).
November 18

Watching directory AND Application Restart/Recovery

 
This is a sample using Visual C++ and Windows API that works with Windows Vista or later.
 
#include
<windows.h>
#include
<process.h>
#include
<iostream>
#include
<functional>

using
namespace std;
using
namespace std::tr1;

#ifdef
_UNICODE
#define
_tcout wcout
#define
_tstring wstring
#else
#define
_tcout cout
#define
_tstring string
#endif

class
DirectoryWatcher
{

public
:
typedef std::tr1::function<void (LPCTSTR)> NotifyChangeHandler;

DirectoryWatcher( const wstring& dir, NotifyChangeHandler changeCallback ) :

Dir_(dir), Started_(false), ChangeCallback_(changeCallback)
{
}

void Start()
{
  if( !Started_ )
  {
    Started_ = true;
    unsigned int threadId;
    HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex( NULL, 0, WatchDirectory, this, NULL, &threadId )); 
    CloseHandle(threadHandle);
  }
}

private
:
  static unsigned int WINAPI WatchDirectory( LPVOID pArguments )
  {
    DirectoryWatcher* w = reinterpret_cast<DirectoryWatcher*>(pArguments);
    w->_WatchDirectory();
    return 0;
  }

  void _WatchDirectory()
  {
    LPCTSTR dir = Dir_.c_str();
    HANDLE handleToWatch = FindFirstChangeNotification( dir, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME );
    if ( INVALID_HANDLE_VALUE == handleToWatch ) 
         ExitProcess(GetLastError()); 

    while (TRUE) 
   
        if( WAIT_OBJECT_0 == WaitForSingleObject( handleToWatch, INFINITE ) ) 
       
            ChangeCallback_( dir );
            if ( !FindNextChangeNotification( handleToWatch ) ) 
                ExitProcess(GetLastError()); 
        }
        else
        {
            ExitProcess(GetLastError()); 
        }
    }
  }

private
:
  DirectoryWatcher(){}
  DirectoryWatcher( const DirectoryWatcher& ){}
  DirectoryWatcher& operator=( const DirectoryWatcher& ){}

  const wstring Dir_;
  bool Started_;

  NotifyChangeHandler ChangeCallback_;
};

void
OnDirectoryChange( LPCTSTR lpDir )
{
  _tcout << TEXT("Refresh the directory ") << lpDir << endl;
}

typedef
std::tr1::function<void (void)> DoRecoveryHandler;

DWORD WINAPI PrepareToRecover( PVOID pArgument )
{
  BOOL bCanceled = FALSE;
  _tcout << TEXT("Preparing recovery...\n");
  ApplicationRecoveryInProgress( &bCanceled );
  if (!bCanceled) 
  {
    if( pArgument )
    {
      DoRecoveryHandler* recoveryFun = reinterpret_cast<DoRecoveryHandler*>(pArgument);
      (*recoveryFun)();
    }
  }
  else
  {
    _tcout << TEXT("Recovery was canceled by the user.\n");
  }

  _tcout << TEXT("Recovery completed...\n");
  ApplicationRecoveryFinished((bCanceled) ? FALSE: TRUE);

  return 0;
}

void
RecoverFromRestart()
{
  _tcout << TEXT("Perform recovery from restart...\n");
}

bool
IsApplicationRestarting( const _tstring& cmdLine, LPCWSTR restartFlag )
{
  return _tstring::npos != cmdLine.find( restartFlag );
}

void
OnDoCustomRecover()
{
  _tcout << TEXT("Custom recovery procedure...\n");
}

int
main()
{
  _tstring cmdLine( GetCommandLine() );
  LPCWSTR restartFlag = TEXT("/restart");
  bool isAppRestarting = IsApplicationRestarting( cmdLine, restartFlag );
  _tcout << TEXT("Command Line = ") << cmdLine.c_str() << TEXT("\n");

  if( isAppRestarting ) RecoverFromRestart();
  HRESULT hr = RegisterApplicationRestart( restartFlag, 0 );
  if( FAILED( hr ) )
  {
    _tcout << TEXT("Restart registration failed\n");
    return 1;
  }

  DoRecoveryHandler customRecovery( OnDoCustomRecover );
  hr = RegisterApplicationRecoveryCallback( PrepareToRecover, &customRecovery, RECOVERY_DEFAULT_PING_INTERVAL, 0 );
  if( FAILED( hr ) )
  {
    _tcout << TEXT("Recovery registration failed\n");
    return 2;
  }
  
  DirectoryWatcher dw( TEXT("D:\\Test\\"), OnDirectoryChange );
  dw.Start();
  if( !isAppRestarting )
  {
    //force restarting...
    Sleep(60 * 1000 + 1 * 1000);
    RaiseException( EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_NONCONTINUABLE_EXCEPTION, NULL, NULL );
  }
  else
  {
  //continue...
  Sleep( 60 * 60 * 1000 );
  }
}

 
According to ARR documentation: "To prevent cyclical restarts, the system will only restart the application if it has been running for a minimum of 60 seconds."
June 24

Two versions for Lock-Free Stack

 
The two codes below are implementations of lock-free stack structure.
The purpose is the same, but the first version can be ported easily to other OSes.
Performance benchmark is a lesson to the reader.
 
The raw C++ implementation. In C++0x we'll change Interlocked APIs to atomic operations:
 
template
<typename T>
struct
LockFreeStack
{
  LockFreeStack() : Head_( NULL ){}

  void Push( T& value )
  {
    PNODE node = new NODE( value );
    PNODE oldHead;

    do
    {
      node->Next = oldHead = Head_;
    }while( oldHead != reinterpret_cast<PNODE>( InterlockedCompareExchangePointer(
                                      reinterpret_cast<volatile PVOID*>(&Head_), node, oldHead )));
  }

  T Pop()
  {
    PNODE node;
    PNODE oldHead;

    do
    {
      oldHead = Head_;
    }while( oldHead != (node = reinterpret_cast<PNODE>( InterlockedCompareExchangePointer(
                                            reinterpret_cast<volatile PVOID*>(&Head_), Head_->Next, oldHead ))));

    T temp = node->Data;
    delete node;
    return temp;
  }

private
:
  typedef struct NODE_TAG
  {
    NODE_TAG( T value ) : Next(NULL), Data(value){}
    NODE_TAG* Next;
    T Data;
  } NODE, *PNODE;

  PNODE Head_;

  LockFreeStack( const LockFreeStack& ){}
  LockFreeStack& operator=( const LockFreeStack& ){}
};


Using a Windows API facility called Singly Linked Lists

template<typename T>
struct LockFreeStack
{
  LockFreeStack()
  {
    Head_ = new_aligned<SLIST_HEADER>();
    if( NULL == Head_ )
      throw "memory allocation failed";

    InitializeSListHead( Head_ );
  }

  ~LockFreeStack()
  {
    InterlockedFlushSList( Head_ );
  }

  void Push( T value )
  {
    Item_ = new_aligned<ITEM>();
    if( NULL == Item_ )
      throw "stack is full";

    Item_->Value = value;
    Entry_ = InterlockedPushEntrySList( Head_, &Item_->Entry );
  }

  T Pop()
  {
    PSLIST_ENTRY tempEntry = InterlockedPopEntrySList( Head_ );
    if( NULL == tempEntry )
      throw "stack is empty";

    Item_ = reinterpret_cast<PITEM>( tempEntry );
    T temp = Item_->Value;
    _aligned_free( tempEntry );
    return temp;
  }

private
:
  typedef struct ITEM_TAG
  {
    SLIST_ENTRY Entry;
    T Value;
  } ITEM, *PITEM;

  PSLIST_ENTRY Entry_;
  PSLIST_HEADER Head_;
  PITEM Item_;

  template <class M> M* new_aligned()
  {
    return reinterpret_cast<M*>(_aligned_malloc( sizeof(M), MEMORY_ALLOCATION_ALIGNMENT ));
  }

  LockFreeStack( const LockFreeStack& ){}
  LockFreeStack& operator=( const LockFreeStack& ){}
};

 

June 13

Samples from my Concurrency Talk at Seminário TempoReal C++ Portabilidade e Performance

  
Samples from my Concurrency Talk at Seminário TempoReal C++ Portabilidade e Performance:
The following code is a C++ port to one of my previous samples: MapReduce with Parallelspace
 
#include
<iostream>
#include
<fstream>
#include
<vector>
#include
<map>
#include
<string>
#include
<boost/thread/thread.hpp>
#include
<boost/thread/mutex.hpp>
#include
<boost/filesystem.hpp>
#include
<boost/function.hpp>
#include
<boost/algorithm/string.hpp>
 
using
namespace std;
using
namespace boost;
using
namespace boost::filesystem;
 
void
get_files( const path& directory, vector<path>& files )
{
  directory_iterator end_iter;
  for( directory_iterator iter( directory ); iter != end_iter; ++iter )
  {
    if( is_directory( iter->status() ) ) continue;
    files.push_back( iter->path() );
  }
}
 
int
get_ProcessorCount(){ return 2; }
 
class TaskExecutor
{
typedef function2<void, map<string, int>&, const map<string, int>&> ConsolidationFunctionType;
typedef function1<map<string, int>, const path&> CountWordsFunctionType;

public:
  TaskExecutor( vector<path>::const_iterator begin, vector<path>::const_iterator end, 
                      const CountWordsFunctionType countWords,
                      const ConsolidationFunctionType consolidation,
                      map<string, int>& result ) : Begin_( begin ), 
                      End_( end ),
                      CountWordsFunction_( countWords ),
                      ConsolidationFunction_( consolidation ),
                      Result_( result ){}

  void operator()()
  {
    for( vector<path>::const_iterator iter = Begin_; iter != End_; ++iter )
      ConsolidationFunction_( Result_, CountWordsFunction_( *iter ) );
  }
 
private
:
  vector<path>::const_iterator Begin_, End_;
  const ConsolidationFunctionType ConsolidationFunction_;
  const CountWordsFunctionType CountWordsFunction_;
  map<string, int>& Result_;
};
 
void
key_count( map<string, int>& dictionary, const string& word, int value )
{
  dictionary[ word ] = dictionary.end() != dictionary.find( word ) ? dictionary[ word ] + value : value;
}
 
map<string, int> map_function( const path& filename )
{
  map<string, int> wordCount;

  ifstream file;
  const int MAXLEN = 1024;
  char line[ MAXLEN ];

  file.open( filename.directory_string().c_str() ); 
 
  while( file.getline( line, MAXLEN ) )
  {
    vector<string> split_v;
    split( split_v, string( line ), is_any_of( " " ) );
    for( vector<string>::const_iterator iter = split_v.begin(); iter != split_v.end(); ++iter )
      key_count( wordCount, *iter, 1 );
  } 
 
  file.close();
  return wordCount;
}
 
void
reduce_function( map<string, int>& destination, const map<string, int>& source )
{
  for( map<string, int>::const_iterator iter = source.begin(); iter != source.end(); ++iter )
  key_count( destination, iter->first, iter->second );
}
 
void
wordcount_mapreduced( const vector<path>& files, map<string, int>& wordCount )
{
  //data partition
  int numberOfPartitions = get_ProcessorCount() * 2; //2 threads per core
  int numberOfFiles = static_cast<int>( files.size() );
  if( numberOfFiles < numberOfPartitions ) numberOfPartitions = numberOfFiles;
  int delta = numberOfFiles / numberOfPartitions;
  vector< map<string, int> > result( numberOfPartitions );
  thread_group tg;
  //for parallel
  for( int step = 0; step < numberOfPartitions; ++step )
  {
    vector<path>::const_iterator begin = files.begin() + delta * step,
    end = numberOfPartitions - 1 == step ? files.end() : files.begin() + delta * step + delta;
    //fork
    tg.create_thread( TaskExecutor( begin, end, map_function, reduce_function, result[step] ) );
  }
 
  //join
  tg.join_all();
  for( vector< map<string, int> >::const_iterator iter = result.begin(); iter != result.end(); ++iter )
    reduce_function( wordCount, *iter );
}
 
int
main()
{
  vector<path> files;
  get_files( "c:\\txttest\\", files );
  map<string, int> wordCount;

  wordcount_mapreduced( files, wordCount );

  for( map<string, int>::const_iterator iter = wordCount.begin(); iter != wordCount.end(); ++iter )
    cout << iter->first << " = " << iter->second << endl;
}
February 25

Get the size of directories from all drives with F#

 
This small F# utility uses recursion to inspect all directories from all drives installed (including network drives mapped).
The sizes are printed in the console screen (or could be redirected).
 
 
#light

open
System.IO
open System

let
ConvertTo (n:int64) (d:float) = n / Convert.ToInt64( d )
//let ConvertToMegabytes (n:int64) = ConvertTo n (1024.0 ** 2.0)
let ConvertToKilobytes (n:int64) = ConvertTo n 1024.0

let
rec getSizeOfDir (path:string) =
    let getSizeOfFiles (dir:string) =
        try
            DirectoryInfo(dir).GetFiles() |> Seq.sumByInt64( fun file -> file.Length )
        with
            | :? UnauthorizedAccessException -> 0L;

    try
        let size = (Directory.GetDirectories( path ) |> Seq.sumByInt64( fun dir -> getSizeOfDir( dir ) )) + getSizeOfFiles( path )
        printfn "Path = %s\r\nSize = %d KB (%d bytes)\r\n" path (ConvertToKilobytes size) size
        size
    with
        | :? UnauthorizedAccessException -> 0L
        | :? IOException -> 0L;

let main = 
    let sw = new Diagnostics.Stopwatch()
    let tm = DateTime.Now
    sw.Start()
    DriveInfo.GetDrives() |> Seq.iter( fun drv -> getSizeOfDir drv.Name |> ignore )
    sw.Stop()
    printfn "\r\n\r\nElapsed time = %s" (sw.Elapsed.ToString())
 
 
This utility could run better if reworked to support threads. Maybe next time... Com sono
 
February 07

XNA, Visual C++ and Guitar Hero


Is it possible to write XNA programs with Visual C++? Yes, it is! Someone show that is possible in F#, too.

The XNA Game Studio 2.0 can be installed inside Visual Studio 2005 Professional (the previous version is hosted only in VC# Express).

The sample below is a Guitar Hero Panel. You plug-in a guitar on PC, and press Fret buttons, Strum bar and Whammy bar to see the feedback. (This sample doesn´t have sounds, just visual feedback)

GHP
 
How can you do to write your own XNA programs with Visual C++?
 
1. Create a XNA Windows Game (or XNA Xbox 360 Game) project with C#. (C# will be the host of the C++/CLI dll. C# is necessary to compile Game Assets like images, fonts, ...)
2. Add a new project Visual C++ CLR Class Library into the current solution. The XNA program will be coded entirely in C++/CLI, here. Is very important (if you want to port to Xbox 360) to compile this project with /clr:safe switch. This ensure that the generated code is MSIL-only. Add reference to the assemblies: Microsoft.Xna.Framework.dll and Microsoft.Xna.Framework.Game.dll. They are at Microsoft XNA install dir something like: <XNA install dir>\XNA Game Studio\v2.0\References\Windows\x86\
3. Add a reference to the VC++ CLR DLL in the C# project. And call the game class written in C++/CLI, at Main method in C# code. (You even have the ability to debug step-by-step) Surpreso
 
The following code is the C++/CLI game program. If you look with attention you see that we have templates and stack semantics:
 
using namespace Microsoft::Xna::Framework;
using namespace Microsoft::Xna::Framework::Graphics;
using namespace Microsoft::Xna::Framework::Input;

namespace
GuitarHeroControlPanel
{

ref struct Piece
{
    Piece( Texture2D^ image, Vector2 position, SpriteBatch^ spriteBatch ) : 
    Display_( false ), Image_( image ), Position_( position ), SpriteBatch_( spriteBatch ){}

    void Update( bool displayStatus ){ Display_ = displayStatus; }
    void Draw()if( Display_ ) SpriteBatch_->Draw( Image_, Position_, Color::White ); }

private:
    bool Display_;
    Vector2 Position_;
    Texture2D^ Image_;
    SpriteBatch^ SpriteBatch_;
};

public ref class GuitarHeroControlPanel : Game
{
public:
    GuitarHeroControlPanel()
    {
        Graphics_ = gcnew GraphicsDeviceManager(this);
        Graphics_->PreferredBackBufferWidth = 1280;
        Graphics_->PreferredBackBufferHeight = 416;
        Window->Title = "Guitar Hero Panel by Fabio Galuppo. Implemented with XNA and Visual C++ 2005. Visit: http://www.gamecultura.com.br/. Blog: http://fabiogaluppo.spaces.live.com/";
        Content->RootDirectory = "Content";
}

private:
    template<class T> T^ CntLoad( System::String^ assetName ){ return Content->Load<T^>( assetName ); }
    template<PlayerIndex P> GamePadButtons GetButtons(){ return GamePad::GetState(P).Buttons; }
    template<PlayerIndex P> GamePadDPad GetDPad(){ return GamePad::GetState(P).DPad; }
    template<PlayerIndex P> GamePadThumbSticks GetThumbSticks(){ return GamePad::GetState(P).ThumbSticks; }
    bool IsPressed( ButtonState bs ){ return bs == ButtonState::Pressed; }

protected:
    virtual void LoadContent() override
    {
        SpriteBatch_ = gcnew SpriteBatch(GraphicsDevice);
        Font_ = CntLoad<SpriteFont>( "Tahoma" );
        GuitarTexture_ = CntLoad<Texture2D>( "guitarhero" );
        GCLogo_ = CntLoad<Texture2D>( "gclogo" );
        VCLogo_ = CntLoad<Texture2D>( "vclogo" );

        GreenFret_ = gcnew Piece( CntLoad<Texture2D>( "green" ), Vector2(965.0, 0.0), SpriteBatch_ );
        RedFret_ = gcnew Piece( CntLoad<Texture2D>( "red" ), Vector2(930.0, 0.0), SpriteBatch_ );
        YellowFret_ = gcnew Piece( CntLoad<Texture2D>( "yellow" ), Vector2(895.0, 0.0), SpriteBatch_ );
        BlueFret_ = gcnew Piece( CntLoad<Texture2D>( "blue" ), Vector2(858.0, 0.0), SpriteBatch_ );
        OrangeFret_ = gcnew Piece( CntLoad<Texture2D>( "orange" ), Vector2(821.0, 0.0), SpriteBatch_ );
        Strum_ = gcnew Piece( CntLoad<Texture2D>( "strum" ), Vector2(269.0, 0.0), SpriteBatch_ );
        Whammy_ = gcnew Piece( CntLoad<Texture2D>( "whammy" ), Vector2(0.0, 259.0), SpriteBatch_ );

        GCLogoVec_ = Vector2( 895.0 , 0.0 );
        VCLogoVecPos_ = Vector2( 250.0, 130.0 ); 
        VCLogoVecOri_ = Vector2( VCLogo_->Width / 2.0f, VCLogo_->Height / 2.0f );
        FontVec_ = Vector2( 880.0, 380.0 ); 
    }

    virtual void Update(GameTime^ gameTime) override 
    {
        if ( IsPressed( GetButtons<PlayerIndex::One>().Back ) ) Game::Exit();

        //Fret Buttons
        GreenFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().A ) );
        RedFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().B ) );
        YellowFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().Y ) );
        BlueFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().X ) );
        OrangeFret_->Update( IsPressed( GetButtons<PlayerIndex::One>().LeftShoulder ) );

        //Strum Bar
        Strum_->Update( IsPressed( GetDPad<PlayerIndex::One>().Up ) || IsPressed( GetDPad<PlayerIndex::One>().Down ) );

        //Whammy Bar
        Whammy_->Update( GetThumbSticks<PlayerIndex::One>().Right.X >= 0.0 );

        Game::Update(gameTime);
    }

    virtual void Draw(GameTime^ gameTime) override
    {
        Graphics_->GraphicsDevice->Clear(Color::CornflowerBlue);
        Game::Draw(gameTime);

        SpriteBatch_->Begin();

            SpriteBatch_->Draw( GuitarTexture_, Vector2::Zero, Color::White );

            GreenFret_->Draw();
            RedFret_->Draw();
            YellowFret_->Draw();
            BlueFret_->Draw();
            OrangeFret_->Draw();
            Strum_->Draw();

            Whammy_->Draw();

            SpriteBatch_->Draw( GCLogo_, GCLogoVec_, Color::White ); 

            SpriteBatch_->Draw( VCLogo_, VCLogoVecPos_, NullRect_, Color::White, -45.0, VCLogoVecOri_, 1.0, SpriteEffects::None, 0.0 );

            SpriteBatch_->DrawString( Font_, "http://fabiogaluppo.spaces.live.com/", FontVec_, Color::Black );

        SpriteBatch_->End();
    }

private:
    GraphicsDeviceManager^ Graphics_;
    SpriteBatch^ SpriteBatch_;
    Texture2D ^GuitarTexture_, ^GCLogo_, ^VCLogo_;
    Vector2 GCLogoVec_, VCLogoVecPos_, VCLogoVecOri_, FontVec_;
    System::Nullable<Rectangle> NullRect_;
    SpriteFont^ Font_;
    Piece ^GreenFret_, ^RedFret_, ^YellowFret_, ^BlueFret_, ^OrangeFret_, ^Strum_, ^Whammy_;
};

};
 
The C# host program:
 
using System;

namespace
GuitarHeroControlPanel
{

static class Program
{
    static void Main()
    {
        using (GuitarHeroControlPanel panel = new GuitarHeroControlPanel()) panel.Run();
    }
}

}
 
Do you like games? Stay tuned at GameCultura   
January 03

TechEd Brasil 2007 - TxF Demo #5

 
How to consume the TxF wrapper with C#:
 
using System;
using System.Transactions;
using System.IO;

class
Program
{
    static void Main(string[] args)
    {
        using (TransactionScope scope = new TransactionScope())
        {
            using (StreamWriter sw = new StreamWriter(NTFS.Transactional.File.OpenTransacted("c:\\ManagedNTFSTx.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None)))            
                for (int i = 0; i < 1000; ++i) sw.WriteLine("Hello World");

            scope.Complete(); //omit this line to rollback transaction 
        }

        using (TransactionScope scope = new TransactionScope())
        {
            NTFS.Transactional.File.CopyTransacted("c:\\ManagedNTFSTx.txt", "c:\\ManagedNTFSTxClone.txt", true);
           
            scope.Complete(); //omit this line to rollback transaction 
        }
    }
}

TechEd Brasil 2007 - TxF Demo #4

 
This managed wrapper is inspired/adapted/improved from this article.
It supports some NTFS transactional file operations like copy, delete, create and open. 
 
using
System;
using
System.IO;
using
System.Security;
using
System.Runtime.InteropServices;
using
System.Runtime.ConstrainedExecution;
using
System.Runtime.CompilerServices;
using
Microsoft.Win32.SafeHandles;
using
System.Transactions;

namespace
NTFS.Transactional
{
    [ComImport, Guid("79427A2B-F895-40e0-BE79-B57DC82ED231"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IKernelTransaction
    {
        int GetHandle(out IntPtr pHandle);
    }

    [SuppressUnmanagedCodeSecurity]
    static class
WindowsAPI
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static extern bool CloseHandle(IntPtr hObject);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern SafeFileHandle CreateFileTransacted
        (
            string lpFileName,
            Constants.FileAccess dwDesiredAccess,
            Constants.FileShare dwShareMode,
            IntPtr lpSecurityAttributes,
            Constants.FileMode dwCreationDisposition,
            int dwFlagsAndAttributes,
            IntPtr hTemplateFile,
            IntPtr hTransaction,
            IntPtr pusMiniVersion,
            IntPtr pExtendedParameter
        );

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern bool CopyFileTransacted
        (
            string lpExistingFileName,
            string lpNewFileName,    
            IntPtr lpProgressRoutine,
            IntPtr lpData,    
            ref bool pbCancel,
            Constants.CopyFile dwCopyFlags,
            IntPtr hTransaction
        );

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        public static extern bool DeleteFileTransacted
        (
            string file, IntPtr transaction
        );

        public static bool SUCCEDDED(int hr) { return hr == Constants.ERROR_SUCCESS; }

        public static void ThrowsLastError() { throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); }

        public static class
Constants
        {
            public const int ERROR_SUCCESS = 0x0;

            [Flags]
            public enum FileAccess
            {
                GENERIC_READ = unchecked((int)0x80000000),
                GENERIC_WRITE = 0x40000000
            }

            [Flags]
            public enum
FileShare
            {
                FILE_SHARE_NONE = 0x0,
                FILE_SHARE_READ = 0x1,
                FILE_SHARE_WRITE = 0x2,
                FILE_SHARE_DELETE = 0x4
            }

            public enum FileMode
            {
                CREATE_NEW = 0x1,
                CREATE_ALWAYS = 0x2,
                OPEN_EXISTING = 0x3,
                OPEN_ALWAYS = 0x4,
                TRUNCATE_EXISTING = 0x5
            }

            [Flags]
            public enum CopyFile
            {
                COPY_FILE_FAIL_IF_EXISTS = 0x1,
                COPY_FILE_RESTARTABLE = 0x2,
                COPY_FILE_OPEN_SOURCE_FOR_WRITE = 0x4,
                COPY_FILE_ALLOW_DECRYPTED_DESTINATION = 0x8,
                COPY_FILE_COPY_SYMLINK = 0x800
            }
        }
    }

    public static class File
    {
        public static void DeleteTransacted(string path)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
                if (!WindowsAPI.DeleteFileTransacted(path, transactionHandle.DangerousGetHandle()))                
                    WindowsAPI.ThrowsLastError();
        }

        public static void CopyTransacted(string from, string to, bool overwrite)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
            {
                bool cancel = false;
                if (!WindowsAPI.CopyFileTransacted
                        (
                            from,
                            to,
                            IntPtr.Zero,
                            IntPtr.Zero,
                            ref cancel,
                            overwrite ? 0 : WindowsAPI.Constants.CopyFile.COPY_FILE_FAIL_IF_EXISTS,
                            transactionHandle.DangerousGetHandle()
                        )
                )
                    WindowsAPI.ThrowsLastError();
            }
        }

        public static FileStream OpenTransacted(string path, FileMode mode, FileAccess access, FileShare share)
        {
            using (KernelTransactionHandle transactionHandle = KernelTransactionHandle.Get())
            {
                SafeFileHandle fileTransactedHandle = WindowsAPI.CreateFileTransacted
                                                                        (
                                                                            path,
                                                                            ToNativeFileAccess(access),
                                                                            ToNativeFileShare(share),
                                                                            IntPtr.Zero,
                                                                            ToNativeFileMode(mode),
                                                                            0,
                                                                            IntPtr.Zero,
                                                                            transactionHandle.DangerousGetHandle(),
                                                                            IntPtr.Zero,
                                                                            IntPtr.Zero
                                                                        );

                if (fileTransactedHandle.IsInvalid) 
                    WindowsAPI.ThrowsLastError();
                return new FileStream(fileTransactedHandle, access);
            }
        }

        static WindowsAPI.Constants.FileAccess ToNativeFileAccess(FileAccess access)
        {
            if (FileAccess.Read == access)
                return WindowsAPI.Constants.FileAccess.GENERIC_READ;
            else if (FileAccess.Write == access)
                return WindowsAPI.Constants.FileAccess.GENERIC_WRITE;
            return WindowsAPI.Constants.FileAccess.GENERIC_READ | WindowsAPI.Constants.FileAccess.GENERIC_WRITE;
        }

        static WindowsAPI.Constants.FileMode ToNativeFileMode(FileMode mode)
        {
            return (WindowsAPI.Constants.FileMode)(int)(FileMode.Append == mode ? FileMode.OpenOrCreate : mode);
        }

        static WindowsAPI.Constants.FileShare ToNativeFileShare(FileShare share)
        {
            return (WindowsAPI.Constants.FileShare)(int)share;
        }
    }

    public class KernelTransactionHandle :
SafeHandleZeroOrMinusOneIsInvalid
    {
        internal KernelTransactionHandle(IntPtr existingHandle) : this(existingHandle, true) { }
        internal KernelTransactionHandle(IntPtr existingHandle, bool ownsHandle) : base(true)
        {
            this.SetHandle(existingHandle);
        }

        protected override bool ReleaseHandle() { return WindowsAPI.CloseHandle(handle); }
       
        public static KernelTransactionHandle Get() { return Get(Transaction.Current); }
        public static KernelTransactionHandle Get(Transaction transaction)
        {
            if (null == transaction)
                throw new NullReferenceException();

            IKernelTransaction kernelTransaction = TransactionInterop.GetDtcTransaction(transaction) as IKernelTransaction;
            KernelTransactionHandle transactionHandler = null;

            RuntimeHelpers.PrepareConstrainedRegions();

            try { }
//CER Scope
            finally
            {
                IntPtr txHandle;
                int hr = kernelTransaction.GetHandle(out txHandle);

                if (!WindowsAPI.SUCCEDDED(hr))
                    throw new System.ComponentModel.Win32Exception(hr);
                transactionHandler = new KernelTransactionHandle(txHandle);
            }
//CER Scope

            return transactionHandler;
        }
    }
}