0

I'm making a small little project that shows step by step how different sorting algorithms work. Essentially just a bunch of random lines drawn with opengl that then get sorted. In order to show it step my step, after each swap in the algorithm I redraw the screen and have the program sleep for about 5 milliseconds. When run inside Visual Studio with the debugger there are no problems at all, but if I run without the debugger, either with ctrl+f5 or from the windows explorer the display will freeze up and stop drawing about half way through the sorting algorithm (regardless of what algorithm) -- However, the console will still output the info (number of comparisons and swaps) at the end, and based on how long it takes, the delay does indeed to still be in effect). I've narrowed this down to be because of sleep function, as when I don't use a sleep it works flawlessly, just too fast. To make things even more strange, I sent the exe to a friend and it worked with no problems for him. I've also tried setting _NO_DEBUG_HEAP to 1 to see if I could catch the error with the debugger attached, but no luck there.

On the chance that something is just weird with Windows.h Sleep(x) I created my own little function using the ctime clock type/function, but still this weird no debugger error continues.

My own sleep function:

void slp(clock_t wait)
{
    clock_t goal;
    goal = wait + clock();
    while(goal > clock());
}

Is there anything that might explain why this will work for one person (my friend) but not myself? Some more code is included below, though I don't believe any of it is an issue, I think its just that I need a better way of sleeping/delaying the program.

/*My window creation/drawing code, just in case its a glut issue some how
(normally I'd use glfw but couldn't get things like glRecti to work for the life of me)*/

constexpr int N = 320;
int heights[ N ];

void gfx();

int main(int argc, char** argv)
{
    for (int i = 0; i < N; i++)
    {
        heights[ i ] = rand() % 600;
    }

    glutInit(&argc, argv);
    glutInitWindowSize(1280, 720);
    int cx = (glutGet(GLUT_SCREEN_WIDTH) - 1280) / 2;
    int cy = (glutGet(GLUT_SCREEN_HEIGHT) - 720) / 2;
    glutInitWindowPosition(cx, cy);
    glutCreateWindow("Sorting Visualizer");
    glutDisplayFunc(gfx);
    glClearColor(0, 0, 0, 1);
    gluOrtho2D(0, 1280, 0, 720);
    glutMainLoop();
    return 0;
}

The gfx function is simply

void gfx()
{
    glClear(GL_COLOR_BUFFER_BIT);
    HeapSorter<int, N> heap(heights);
    heap.sort();
    heap.printInfo();
}

And now the sorting algorithm:

template <typename T, int N>
class HeapSorter : public Sorter<T, N>
{
    using Sorter<T, N>::drawStep;
    using Sorter<T, N>::mSwaps;
    using Sorter<T, N>::mCompares;
    using Sorter<T, N>::mArr;
    using Sorter<T, N>::mName;
public:
    HeapSorter(T arr[ N ], int slp = 5) : Sorter<T, N>("Heap Sort", arr, slp) {}

    void sort()
    {
        for (int i = N / 2 - 1; i >= 0; i--)
        {
            heapify(N, i);
        }


        for (int i = N - 1; i > 0; i--)
        {
            std::swap(mArr[ 0 ], mArr[ i ]);
            mSwaps++;
            drawStep();
            heapify(i, 0);
        }
    }

private:
    void heapify(const int n, int i)
    {
        int largest = i;
        int left = 2 * i + 1;
        int right = 2 * i + 2;

        ++mCompares;
        if (left < n && mArr[ left ] > mArr[ largest ])
        {
            largest = left;
        }

        ++mCompares;
        if (right < n && mArr[ right ] > mArr[ largest ])
        {
            largest = right;
        }

        if (largest != i)
        {
            std::swap(mArr[ i ], mArr[ largest ]);
            ++mSwaps;
            drawStep();
            heapify(n, largest);
        }
    }
};

The super class just handles drawing, the sleep function occurs in drawStep

template <typename T, int N>
class Sorter
{
public:
    Sorter(std::string name, T arr[ N ], const int slp = 5) :
        mName(std::move(name)),
        mSleep(slp)
    {
        for (auto i = 0; i < N; i++)
        {
            mArr[ i ] = arr[ i ];
        }
    }

    void printInfo() const
    {
        std::cout << mName << " - Compares: " << mCompares << " - Swaps: " << mSwaps << "\n";
    }

protected:


    static void drawText(const float x, const float y, const std::string& txt)
    {
        glColor3f(1, 1, 1);
        glRasterPos2f(x, y);

        for (auto i : txt)
        {
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, i);
        }
    }

    void drawStep()
    {
        glClear(GL_COLOR_BUFFER_BIT);

        drawText(5, 700, mName);
        drawText(5, 680, "Compares: " + std::to_string(mCompares));
        drawText(5, 660, "Swaps: " + std::to_string(mSwaps));
        drawText(5, 640, "Sleep: " + std::to_string(mSleep) + " ms");

        glColor3f(1.f, 0.f, 0.f);

        for (auto i = 0; i < N; i++)
        {
            glRecti(4 * i, 100, 4 * i + 3, 100 + mArr[ i ]);
        }

        glFlush();
        SLP(mSleep);
    }

    std::string mName;
    int mSleep;
    int mCompares = 0;
    int mSwaps = 0;

    T mArr[ N ];
};

SLP is simply a macro so I could quickly test different sleep functions without having to change any place I might have used it

  • `while(goal > clock());` does nothing and any compiler worth using will optimize it out. – user4581301 Feb 22 '21 at 21:36
  • I'm not familiar with glut but I'm pretty sure glutDisplayFunc should only draw a single frame, e.g. see https://stackoverflow.com/questions/4206472/understanding-the-relationship-between-glutdisplayfunc-and-glutpostredisplay – Alan Birtles Feb 22 '21 at 21:39
  • 1
    @Tas As mentioned at the bottom of my post, SLP is a macro I created so I can easily switch between windows' Sleep and my slp, (and sleep for when on Unix) – TigerCipher Feb 22 '21 at 21:52
  • @AlanBirtles To my understanding `glutPostRedisplay` would cause my gfx function to get called again, which is not what I would want, that would restart the sorting. The way I'm doing it now with `glClear` works, it's just the sleeps/delays that are causing issues – TigerCipher Feb 22 '21 at 21:54
  • @user4581301 Maybe it changes it, but it doesn't optimize it out, as the delay caused by that while statement does indeed work – TigerCipher Feb 22 '21 at 21:56

0 Answers0