Skip to content

Instantly share code, notes, and snippets.

@kennykerr kennykerr/Words.cpp
Created May 5, 2015

Embed
What would you like to do?
#include <cctype>
#include <chrono>
#include <map>
#include <unordered_map>
#include <string>
#include <ppl.h>
#include <windows.h>
#include <wrl.h>
namespace wrl = Microsoft::WRL::Wrappers;
namespace ppl = concurrency;
typedef std::chrono::high_resolution_clock clock_type;
typedef std::chrono::duration<double> real_duration;
using std::chrono::duration_cast;
#define ASSERT(expr) _ASSERTE(expr)
#ifdef _DEBUG
#define VERIFY(expr) ASSERT(expr)
#else
#define VERIFY(expr) (expr)
#endif
class file_view
{
char const * m_view;
LARGE_INTEGER m_size;
typedef wrl::HandleT<wrl::HandleTraits::HANDLENullTraits> MapHandle;
file_view(file_view const&); // not implemented
file_view& operator=(file_view const&); // not implemented
public:
file_view(char const * name) throw() :
m_view(),
m_size()
{
ASSERT(name);
wrl::FileHandle const file(CreateFile(name,
GENERIC_READ,
FILE_SHARE_READ,
nullptr, // default security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr)); // no template
if (!file.IsValid()) return;
VERIFY(GetFileSizeEx(file.Get(), &m_size));
if (m_size.QuadPart == 0) return;
MapHandle const map(CreateFileMapping(file.Get(),
nullptr, // default security
PAGE_READONLY,
0, 0, // match file size
nullptr)); // no name
VERIFY(map.IsValid());
m_view = static_cast<char const *>(MapViewOfFile(map.Get(),
FILE_MAP_READ,
0, 0, // offset
0)); // match file size
}
~file_view() throw()
{
if (valid())
{
VERIFY(UnmapViewOfFile(m_view));
}
}
bool valid() const throw() // If !valid() call GetLastError for reason
{
return nullptr != m_view;
}
char const * begin() const throw()
{
ASSERT(valid());
return m_view;
}
char const * end() const throw()
{
return begin() + m_size.QuadPart;
}
};
int main(int argc, char ** argv)
{
auto const start_time = clock_type::now();
typedef std::unordered_map<std::string, unsigned> word_map;
ppl::combinable<word_map> shared;
ppl::parallel_for_each(argv + 1, argv + argc, [&](char const * name)
{
file_view const file(name);
if (!file.valid()) return;
auto & result = shared.local();
char const * word_first = nullptr;
for (auto it = file.begin(); it != file.end(); ++it)
{
if (*it < 0 || (!std::isalnum(*it) && *it != '_'))
{
if (word_first)
{
++result[std::string(word_first, it)];
}
word_first = nullptr;
}
else if (!word_first)
{
word_first = it;
}
}
if (word_first)
{
++result[std::string(word_first, file.end())];
}
});
word_map * largest = nullptr;
shared.combine_each([&] (word_map & source)
{
if (!largest || largest->size() < source.size())
{
largest = &source;
}
});
shared.combine_each([&] (word_map & source)
{
if (largest != &source)
{
word_map & result = *largest;
for (auto const & w : source)
{
result[w.first] += w.second;
}
}
});
auto const end_time = clock_type::now();
double const elapsed = duration_cast<real_duration>(end_time - start_time).count();
//for (auto const & w : result)
//{
// printf("%s: %u\n", w.first.c_str(), w.second);
//}
if (largest)
{
printf("\nWords: %u Seconds: %.2f\n", static_cast<unsigned>(largest->size()), elapsed);
}
}
@kennykerr

This comment has been minimized.

Copy link
Owner Author

commented May 5, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.