<tb@panthema.net>
<http://www.gnu.org/licenses/>
#ifndef WSORTVIEW_H
#define WSORTVIEW_H
#include <wx/wx.h>
#include <wx/thread.h>
#include <wx/log.h>
#include <vector>
#include <algorithm>
#define ASSERT(cond) do { if (!(cond)) { \
wxLogError(_("Assertion failed:\n%s in %s:%d"), \
_T(#cond), _T(__FILE__), __LINE__); \
wxLog::FlushActive(); \
abort(); \
} } while(0)
extern bool g_sound_on;
extern double g_sound_sustain;
void SoundCallback(void *udata, unsigned char *stream, int len);
void SoundReset();
void SoundAccess(size_t i);
extern size_t g_compare_count;
extern size_t g_access_count;
class ArrayItem
{
public:
typedef int value_type;
protected:
value_type value;
public:
ArrayItem() {}
explicit ArrayItem(const value_type& d) : value(d) {}
ArrayItem(const ArrayItem& v) : value(v.value) {}
const value_type& get() const
{ OnAccess(*this); return value; }
static void OnAccess(const ArrayItem& a);
const value_type& get_direct() const
{ return value; }
bool operator== (const ArrayItem& v) const
{ OnComparison(*this,v); return (value == v.value); }
bool operator!= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value != v.value); }
bool operator< (const ArrayItem& v) const
{ OnComparison(*this,v); return (value < v.value); }
bool operator<= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value <= v.value); }
bool operator> (const ArrayItem& v) const
{ OnComparison(*this,v); return (value > v.value); }
bool operator>= (const ArrayItem& v) const
{ OnComparison(*this,v); return (value >= v.value); }
int cmp(const ArrayItem& v) const
{ OnComparison(*this,v); return (value == v.value ? 0 : value < v.value ? -1 : +1); }
bool equal_direct(const ArrayItem& v) const
{ return (value == v.value); }
bool less_direct(const ArrayItem& v) const
{ return (value < v.value); }
bool greater_direct(const ArrayItem& v) const
{ return (value > v.value); }
static void OnComparison(const ArrayItem& a, const ArrayItem& b);
};
extern double g_delay;
extern bool g_algo_running;
extern wxString g_algo_name;
class WSortView : public wxPanel
{
public:
WSortView(wxWindow *parent, int id, class WMain_wxg* wmain);
~WSortView();
class WMain* wmain;
void RepaintNow();
virtual void OnPaint(wxPaintEvent& pe);
virtual void OnSize(wxSizeEvent& se);
void paint(wxDC& dc, const wxSize& dcsize);
public:
DECLARE_EVENT_TABLE();
protected:
std::vector<ArrayItem> m_array;
ArrayItem::value_type m_array_max;
bool m_calc_inversions;
ssize_t m_inversions;
struct Access
{
unsigned int index;
unsigned short color;
unsigned short sustain;
unsigned short priority;
Access(size_t i=0, unsigned short c=1,
unsigned short s=0, unsigned short p=0)
: index(i), color(c), sustain(s), priority(p) { }
};
Access m_access1, m_access2;
std::vector<Access> m_access_list;
wxMutex m_mutex;
std::vector<unsigned char> m_mark;
std::vector< std::pair<volatile ssize_t*,unsigned char> > m_watch;
bool m_is_sorted;
bool m_stepwise;
wxSemaphore m_step_semaphore;
public:
void OnAlgoLaunch(const struct AlgoEntry& ae);
void ToggleCalcInversions();
void FillData(unsigned int schema, size_t arraysize);
void FillInputlist(wxControlWithItems* list);
bool IsSorted() const { return m_is_sorted; }
void CheckSorted();
void SetStepwise(bool v) { m_stepwise = v; }
void DoStepwise();
ssize_t GetInversions() const
{ return m_inversions; }
size_t GetRuns() const;
protected:
void ResetArray(size_t size);
void FinishFill();
void OnAccess();
void SaveAccess(size_t i);
short InAccessList(ssize_t idx);
unsigned short InWatchList(ssize_t idx) const;
void RecalcInversions();
void UpdateInversions(size_t i, size_t j);
public:
size_t size() const { return m_array.size(); }
const ArrayItem::value_type& array_max() const
{ return m_array_max; }
void DoDelay(double delay);
const ArrayItem& direct(size_t i) const
{
ASSERT(i < m_array.size());
return m_array[i];
}
const ArrayItem& operator[](size_t i)
{
ASSERT(i < m_array.size());
if (m_access1.index != i)
{
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
}
OnAccess();
}
return m_array[i];
}
ArrayItem& get_mutable(size_t i)
{
ASSERT(i < m_array.size());
if (m_access1.index != i)
{
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
}
OnAccess();
}
RecalcInversions();
return m_array[i];
}
const ArrayItem& get_nocount(size_t i)
{
ASSERT(i < m_array.size());
if (m_access1.index != i)
{
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
}
--g_access_count;
OnAccess();
}
return m_array[i];
}
void set(size_t i, const ArrayItem& v)
{
ASSERT(i < m_array.size());
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access_list.push_back(i);
m_array[i] = v;
}
RecalcInversions();
OnAccess();
}
void swap(size_t i, size_t j)
{
ASSERT(i < m_array.size());
ASSERT(j < m_array.size());
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = i;
m_access2 = j;
m_access_list.push_back(i);
m_access_list.push_back(j);
}
UpdateInversions(i, j);
OnAccess();
std::swap(m_array[i], m_array[j]);
OnAccess();
m_access2 = -1;
}
void touch(size_t i, int color = 2,
unsigned short sustain = 0, unsigned short priority = 0)
{
ASSERT(i < m_array.size());
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access1 = Access(i, color, sustain, priority);
m_access_list.push_back( Access(i, color, sustain, priority) );
}
}
void mark(size_t i, int color = 2)
{
ASSERT(i < m_array.size());
m_mark[i] = color;
}
void mark_swap(size_t i, size_t j)
{
ASSERT(i < m_array.size());
ASSERT(j < m_array.size());
std::swap(m_mark[i], m_mark[j]);
}
void unmark(size_t i)
{
ASSERT(i < m_array.size());
m_mark[i] = 0;
}
void unmark_all()
{
m_access1 = m_access2 = -1;
std::fill(m_mark.begin(), m_mark.end(), 0);
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_access_list.clear();
}
void watch(volatile ssize_t* idxptr, unsigned char color = 2)
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_watch.push_back( std::make_pair(idxptr,color) );
}
void unwatch_all()
{
wxMutexLocker lock(m_mutex);
ASSERT(lock.IsOk());
m_watch.clear();
}
};
class SortAlgoThread : public wxThread
{
protected:
class WMain* m_wmain;
class WSortView& m_array;
size_t m_algo;
public:
SortAlgoThread(class WMain* wmain, class WSortView& array, size_t algo);
virtual ExitCode Entry();
void Exit();
};
#endif