00:00
00:00
Newgrounds Background Image Theme

Hyper-Neko-Gold just joined the crew!

We need you on the team, too.

Support Newgrounds and get tons of perks for just $2.99!

Create a Free Account and then..

Become a Supporter!

Programming Regs Lounge

714,981 Views | 15,737 Replies
New Topic Respond to this Topic

Response to Programming Regs Lounge 2014-01-05 17:00:27


At 1/4/14 08:15 PM, Diki wrote: Using multiple ports also would not prevent that from happening, as multiple ports don't affect the amount resources available on the system.

I see. So what you're saying is it is more likely that the system would run out of memory before a port gets clogged?

To allow me to input commands (for testing purposes) and receive console output at the same time I had to use threads, since capturing input is a blocking operation.

Haha that does make sense. I can see some advantages of threading. I guess I won't really fully understand until I dive into it. I'm just now returning to C++ though so it's not likely I'll get to threads any time soon.

No worries. I like talking about programming and computer science, and all that..

Well thank you very much for all the info! Getting to talk with an experienced vet isn't an opportunity come by often (especially since it's quite slow around these parts, haha but I jest).


BBS Signature

Response to Programming Regs Lounge 2014-01-05 23:35:47


At 1/5/14 05:00 PM, coln wrote: I see. So what you're saying is it is more likely that the system would run out of memory before a port gets clogged?

Well, the port will never "get clogged", just like an IP address can never be clogged. The port is just a numerical representation of a destination for a socket. And the system running out of memory is just one possibility. For example, imagine a system that has 1GB of usable RAM, and every time it receives a connection it allocates 100KB and deallocates the 100KB when the connection is lost. Let's say it takes the system 2ms to allocate, and 6ms to deallocate (those numbers aren't based on anything). That means it takes three times as long to deallocate the memory (for whatever reason) than it does to allocate it, which means the system is capable of allocating memory faster than it deallocates it. If someone were to continually send socket connections to the system it would just keep allocating memory faster than it deallocates it, eventually run out of usable RAM, and will attempt to allocate memory it has no access to and probably segfault.

In that scenario, even if you were to use multiple ports the system would still run out of memory, because even though a different port is being used the connection is still sent to the same server (although probably in a different application or thread, but the same server all the same).

It would take some very short-sighted design for something like that to happen, but there you go.

At 1/5/14 05:00 PM, coln wrote: Haha that does make sense. I can see some advantages of threading. I guess I won't really fully understand until I dive into it. I'm just now returning to C++ though so it's not likely I'll get to threads any time soon.

Well if you ever want to you can. I wasn't exaggerating when I said that using threads is easy:

#include <iostream>
#include <thread>

void mythread() {
	std::cout << "I am a thread" << std::endl;
}

int main() {
	std::thread foo(mythread);
}

That's all that is required to run a thread. Each thread is just a function that you pass to the thread class. If you wanted to do some kind of update loop you just need to put your loop inside your function, and call the join() function:

#include <chrono>
#include <iostream>
#include <thread>

void mythreadA() {
	while (true) {
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Hello from mythreadA" << std::endl;
	}
}

void mythreadB() {
	while (true) {
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Hello from mythreadB" << std::endl;
	}
}

int main() {
	std::thread foo(mythreadA);
	std::thread bar(mythreadB);
	
	foo.join();
	bar.join();
}

The hard part is getting the threads to work with each other. For example, see if you can figure out how to make the threads not output both lines of text at the same time, and instead have it alternate between outputting Hello from mythreadA and Hello from mythreadB each second.

Incidentally I also know C++ pretty well, so if you ever have trouble learning it feel free to ask any questions, such as regarding pointers (when I was learning C++ it took me a while to wrap my head around pointers).

Response to Programming Regs Lounge 2014-01-06 00:51:17


Also, I figure I should point out that you shouldn't use an iostream in a thread like I did in that example. Nothing wrong with doing it for the sake of learning, like I did there, but any real applications should never do that (iostreams aren't thread-safe).

Response to Programming Regs Lounge 2014-01-06 01:00:07


And another thing I forgot to point out (sure would be nice if we could edit posts). It's unlikely that the system itself would crash in that scenario, just the application, since the OS should be smart enough to not allow itself to run out memory. The application, on the other hand, is only as smart as you tell it to be.

Response to Programming Regs Lounge 2014-01-18 15:42:40


Last week I made a post in the Flash lounge about C, which you can read here, where I slapped together a very basic linked list. I didn't really have anything better to do today, so I added a bunch of missing functionality such as the ability to deallocate the list, insert data in the middle of the list, and a function to make iteration easier (among some other things).

The source code is here.

Here's a basic implementation that just pushes three integers:

#include "list.c"

int main(int argc, char** argv) {
    struct List mylist;
    int temp;

    list_init(&mylist);

    temp = 1;
    list_push_back(&mylist, &temp, sizeof(temp));

    temp = 2;
    list_push_back(&mylist, &temp, sizeof(temp));

    temp = 3;
    list_push_back(&mylist, &temp, sizeof(temp));

    list_destroy(&mylist);

    return 0;
}

And here's a more complex implementation that does a bunch of shit:

#include <stdio.h>
#include "list.c"

int main(int argc, char** argv) {
    struct List mylist;
    int temp;

    list_init(&mylist);

    // Insert "1" at the end of the list
    temp = 1;
    list_push_back(&mylist, &temp, sizeof(temp));

    // Insert "2" at the beginning of the list
    temp = 2;
    list_push_front(&mylist, &temp, sizeof(temp));

    // Insert "3" at the end of the list
    temp = 3;
    list_push_back(&mylist, &temp, sizeof(temp));

    // Insert "9999" at index positions 1 and 3
    temp = 9999;
    list_insert(&mylist, 1, &temp, sizeof(temp));
    list_insert(&mylist, 3, &temp, sizeof(temp));

    // Output the size of the list
    printf("There are %u elements in the list\n\n", list_size(&mylist));

    // Get the element at index position 2
    int *pdataBeforeRmv = list_at(&mylist, 2);
    printf("Index #2 => %d\n", *pdataBeforeRmv);

    // Remove the element at index position 2
    list_remove(&mylist, 2);

    // Get the new element at index position 2
    int *pdataAfterRmv = list_at(&mylist, 2);
    printf("Index #2 => %d\n\n", *pdataAfterRmv);

    // Output the size of the list
    printf("There are %u elements in the list\n\n", list_size(&mylist));

    // Iterate over each element and print the value
    struct ListNode *itr = mylist.head;
    size_t index = 0;
    int buffer = 0;

    while (list_next(&itr, &buffer, sizeof(buffer))) {
        printf("Index #%u => %d\n", index++, buffer);
    }

    printf("\n");

    // Iterate over each element, in reverse, and print the value
    itr = mylist.tail;
    index = list_size(&mylist)-1;
    buffer = 0;

    while (list_prev(&itr, &buffer, sizeof(buffer))) {
        printf("Index #%u => %d\n", index--, buffer);
    }

    printf("\n");

    if (list_empty(&mylist)) printf("The list is empty\n");
    else printf("The list is not empty\n");

    // Deallocate the list
    list_destroy(&mylist);

    if (list_empty(&mylist)) printf("The list is empty\n");
    else printf("The list is not empty\n");

    return 0;
}

Just a silly little thing that I put together for fun. I might take a crack at writing a binary tree next, which will be trickier.

P.S.
I only tested this with GCC, and it probably won't work if you try to compile it with MSVC. There shouldn't be any errors, warnings or memory leaks, unless I missed something.

Response to Programming Regs Lounge 2014-01-21 21:11:30


I personally like to program in C
C is God's programming language.

Response to Programming Regs Lounge 2014-01-23 12:51:42


At 1/6/14 01:00 AM, Diki wrote: And another thing I forgot to point out (sure would be nice if we could edit posts). It's unlikely that the system itself would crash in that scenario, just the application, since the OS should be smart enough to not allow itself to run out memory. The application, on the other hand, is only as smart as you tell it to be.

I apologize for forgoing a response to this; I've been wildly busy. After a bit of research into your original question (how to make the threads output one at a time), I could not find an answer. From what I gathered join() brought them together. The only thing I can think of is make one wait() before calling cout then make another wait() after calling cout().

Phew! I also learned a bit too, but I've got so much more to learn about threads and so little time to do it right now. I mean, I still need to learn about linked lists (which should be easy since you just posted a great example), databases, file i/o, and threads. Maybe some sorting in there too.


BBS Signature

Response to Programming Regs Lounge 2014-01-23 16:39:45


At 1/21/14 09:11 PM, Chrisman33 wrote: I personally like to program in C
C is God's programming language.

Yeah, it's a fantastic language. It can get pretty hairy once you start doing complex operations over thousands of lines of code, though. And the number of things that cause undefined behaviour can be a pain in the ass, but that comes with the territory.

At 1/23/14 12:51 PM, coln wrote: From what I gathered join() brought them together.

The join() method just makes the main function block until both of those threads complete. Without calling that method the main function would complete, which would terminate the program, making the threads stop running.

At 1/23/14 12:51 PM, coln wrote: The only thing I can think of is make one wait() before calling cout then make another wait() after calling cout().

Well, you are correct about that. To do that you need to use a mutex, which is a portmanteau word of "mutual exclusion". Basically they work by creating one mutex for every thread you want to be able to share functionality or data, in this case sending data to cout, and locking and unlocking it each time that is done.

Like this:

#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>

std::mutex GLOBAL_MUTEX;

void mythreadA() {
	while (true) {
		GLOBAL_MUTEX.lock();
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Hello from mythreadA" << std::endl;
		GLOBAL_MUTEX.unlock();
	}
}

void mythreadB() {
	while (true) {
		GLOBAL_MUTEX.lock();
		std::this_thread::sleep_for(std::chrono::seconds(1));
		std::cout << "Hello from mythreadB" << std::endl;
		GLOBAL_MUTEX.unlock();
	}
}

int main() {
	std::thread foo(mythreadA);
	std::thread bar(mythreadB);
	
	foo.join();
	bar.join();
}

By locking the mutex in one of the threads it forces the other thread to block until the thread that locked it unlocks it. In other words what is happening is this:

- myThreadA() is called first. It locks the mutex.
- myThreadB() is called second. It attempts to lock the mutex, but it is already locked, so the thread blocks.
- myThreadA() waits 1 second, sends output to cout, and unlocks the mutex.
- myThreadB() stops blocking because the mutex is now unlocked, and locks the mutex.
- myThreadA() attempts to lock the mutex, but it is now locked, so the thread blocks.
- myThreadB() waits 1 second, sends output to cout, and unlocks the mutex.

And that just repeats.

Pretty simple once you know how to do it.

At 1/23/14 12:51 PM, coln wrote: Phew! I also learned a bit too, but I've got so much more to learn about threads and so little time to do it right now. I mean, I still need to learn about linked lists (which should be easy since you just posted a great example), databases, file i/o, and threads. Maybe some sorting in there too.

Linked lists are pretty straight forward. They're just a collection of nodes/elements that contain data, and a link/pointer to the "next" node/element (if it's a singly linked list) or a link/pointer to both the "next" and "prev" nodes/elements (if it's a doubly linked list, which is what I made in C in the post you're talking about).

File I/O in C or C++ is pretty damned easy. Here's two basic examples:

C

#include <stdio.h>

int main(int argc, char** argv) {
    char buffer;
    FILE *fHandle = fopen("myFile.txt", "r");

    while ((buffer = getc(fHandle)) != EOF) {
        putchar(buffer);
    }
    
    return 0;
}

C++

#include <fstream>
#include <iostream>
#include <string>

int main(int argc, char** argv) {
    std::string buffer;
    std::ifstream file("myFile.txt");

	while (getline(file, buffer)) {
		std::cout << buffer << std::endl;
	}

	file.close();

	return 0;
}

For the sake of simplicity I didn't include safety checks, such as ensuring that the file was successfully opened, but that's as easy as including a single if statement.

Threads I've already covered, and sorting is a bit too complex to get into in just one post like this. I haven't ever worked with databases in C/C++ since I prefer doing that sort of thing in a higher level language (e.g. Python or Ruby).

Response to Programming Regs Lounge 2014-01-25 07:31:13


Been improving my EasyXInput project that I posted on here around a year ago. Most of the changes were cleaning up the code, which has no affect on the implementation, but I also renamed the namespace, and some of the functions and preprocessor definitions.

For anyone who doesn't know what EasyXInput is it's a lightweight framework for managing input from XInput-enabled devices, such as Xbox 360 controllers.

The basic implementation is like this now:

#include <windows.h>
#include <xinput.h>
#include <iostream>

#include "easyx.hpp"

int main() {
    while (true) {
        easyx::update();
        easyx::Event evt;

        while (easyx::poll(&evt)) {
            switch (evt.type) {
            case EASYX_EVENT_CONNECT:
                std::cout << "Controller Connected" << std::endl;
                break;
            case EASYX_EVENT_DISCONNECT:
                std::cout << "Controller Disconnected" << std::endl;
                break;
            case EASYX_EVENT_PRESS:
                std::cout << "Pressed the " << easyx::name(evt.which) << " button" << std::endl;
                break;
            case EASYX_EVENT_RELEASE:
                std::cout << "Released the " << easyx::name(evt.which) << " button" << std::endl;
                break;
            }
        }
    }
}

I basically wanted to make everything more clear and succinct. I'm also going to be using this to make an application that will be similar to XPadder, because I don't like XPadder.

The improvements are almost finished, but I still have some work to do. Once it's all done I'll post the new source code.

Response to Programming Regs Lounge 2014-01-25 13:35:31


At 1/23/14 04:39 PM, Diki wrote: Yeah, it's a fantastic language. It can get pretty hairy once you start doing complex operations over thousands of lines of code, though. And the number of things that cause undefined behaviour can be a pain in the ass, but that comes with the territory.

Do you prefer C or C++? Or does it depend on what you're doing?

By locking the mutex in one of the threads it forces the other thread to block until the thread that locked it unlocks it. In other words what is happening is this:

Ahh I see. What happens when you don't put a loop in the threads? When threadA runs, then threadB gets blocked, would nothing happen after that? Or since it's linear top-down compilation it would run A then B and no conflicts would arise?

Linked lists are pretty straight forward.

I read something somewhere about linked lists that asked, "Why would you want to learn about linked lists?" And their answer was "it's knowledge that *someone* will eventually use hopefully. " Haha.

File I/O in C or C++ is pretty damned easy. Here's two basic examples:
Threads I've already covered, and sorting is a bit too complex to get into in just one post like this. I haven't ever worked with databases in C/C++ since I prefer doing that sort of thing in a higher level language (e.g. Python or Ruby).

Hey, I can't thank you enough for writing this all up. I really do appreciate you helping out a random stranger learn how to program. Hopefully I'll have some time to write up some simple programs and see how I do.


BBS Signature

Response to Programming Regs Lounge 2014-01-25 17:17:24


At 1/25/14 01:35 PM, coln wrote: Do you prefer C or C++? Or does it depend on what you're doing?

For the most part I prefer C++ because C is a procedural language, which can make things get verbose pretty fast. C is a great language and all, but I like working with classes, and C doesn't have classes.

At 1/25/14 01:35 PM, coln wrote: Ahh I see. What happens when you don't put a loop in the threads? When threadA runs, then threadB gets blocked, would nothing happen after that? Or since it's linear top-down compilation it would run A then B and no conflicts would arise?

If there were no loops then it would do the same thing, except only once. You would still need the mutex and join() calls, because without the mutex both threads could end up sending data to cout at the same time, and without the join() calls the main function will exit while the threads are sending the data.

At 1/25/14 01:35 PM, coln wrote: I read something somewhere about linked lists that asked, "Why would you want to learn about linked lists?" And their answer was "it's knowledge that *someone* will eventually use hopefully. " Haha.

You should learn about linked lists because if you don't know how the structure works then you won't know when you need to use one. The C++ STL (Standard Template Library) has several data structures (e.g. vector, list, map, set, queue) and they all have their own special features and pros/cons.

For example a vector is just a dynamically allocating array, which means it will grow in size as you add more elements to it (arrays in C/C++ can never be resized without reallocating memory). Since the memory is just an array it makes accessing elements in the middle of the array fast, but on the other hand it makes inserting elements into the middle, and especially the beginning, slow because it has to shift all the elements in front of where you're inserting ahead by one. So if you have this data stored in a vector:

1  2  3  4  5  6  7  8  9  10

And you want to insert "99" after the "3" then all elements after the "3" need to be moved forward by one. If there is not enough memory to shift the elements forward then more memory has to be allocated before that can be done, making the process even slower. However that wouldn't happen with only ten elements because the memory capacity of vectors grow exponentially by powers of two, so that vector would have the capacity to store sixteen elements as you can see here.

A linked list is basically the opposite of a vector in regard to the performance I described. Accessing elements in the middle of a linked list is slow because each element is separate from each element, meaning it's not using an array, so each element needs to be iterated over until the desired index position is reached. However, this makes inserting elements anywhere in the list faster than inserting anywhere in a vector other than the back (for the most part). This is especially true for inserting an element at the beginning of a list because it just needs to allocate one element, and then link it on at the beginning.

All comes down to how you intend to use the structure. Need to access elements anywhere in the structure, but rarely insert them anywhere? Use a vector. Need to insert elements anywhere in the structure, but rarely access them anywhere? Use a list.

At 1/25/14 01:35 PM, coln wrote: Hey, I can't thank you enough for writing this all up. I really do appreciate you helping out a random stranger learn how to program. Hopefully I'll have some time to write up some simple programs and see how I do.

No worries, man. It's my pleasure.

Response to Programming Regs Lounge 2014-01-26 14:16:49


At 1/25/14 05:17 PM, Diki wrote: And you want to insert "99" after the "3" then all elements after the "3" need to be moved forward by one. If there is not enough memory to shift the elements forward then more memory has to be allocated before that can be done, making the process even slower. However that wouldn't happen with only ten elements because the memory capacity of vectors grow exponentially by powers of two, so that vector would have the capacity to store sixteen elements as you can see here.

So a vector just adds padding, like structs do? Speaking of that, what's the point of this (in both vectors and structs)? I see that vectors would use it to be a little more efficient, but why would structs need extra padding?

All comes down to how you intend to use the structure. Need to access elements anywhere in the structure, but rarely insert them anywhere? Use a vector. Need to insert elements anywhere in the structure, but rarely access them anywhere? Use a list.

I understand this, but where would you need to have efficient inserting over accessing? I am having difficulty thinking of an example where you wouldn't need to access the elements often.


BBS Signature

Response to Programming Regs Lounge 2014-01-26 18:55:20


At 1/26/14 02:16 PM, coln wrote: So a vector just adds padding, like structs do?

No, a vector is not like a struct (i.e. a C struct; structs in C++ are just classes with public members by default, though the principle is the same anyway). The vector isn't adding padding, it's just a dynamically allocating array that exponentially increases the amount of memory available to store data. Like this:

int main() {
    // Make one element array
    int size = 1;
    int *data = new int[size];
    data[0] = 1;

    // Re-size to two elements
    delete data;
    size = size*2;
    data = new int[size];
    data[0] = 1;
    data[1] = 2;

    // Re-size to Four elements
    delete data;
    size = size*2;
    data = new int[size];
    data[0] = 1;
    data[1] = 2;
    data[2] = 3;
    data[3] = 4;
}

The vector class is more complicated than that, and those technically aren't arrays, but that's the general idea. Without going into too much detail the vector class implements that type of behaviour by keeping three pointers: a begin pointer, an end pointer, and a capacity pointer. Kind of like this:

class MyVector {
private:
    int *_pbegin;
    int *_pend;
    int *_pcapacity;
public:
    MyVector(int size) {
        _pbegin = new int[size];
        _pend = _pbegin;
        _pcapacity = _pbegin + size;
    }

    ~MyVector() {
        delete _pbegin;
    }
};

int main() {
    MyVector vec(10);
}

Note: Like above the actual vector class is much more complicated than this, as this basic example doesn't even use templates or have any ability to add elements.

The begin pointer points to where the sequence of data starts. The end pointer points to the last element, which will be the same as the begin pointer if there are no elements (not the same as having no memory allocated). The capacity pointer points to where the end of the sequence is. As elements are added into the vector the end pointer will move forward by one, and when it reaches the capacity pointer that means more memory is required, which is when the capacity would be doubled.

To help understand how the vector works I wrote a very basic implementation that works with the same principle (but it does lack many of the vector's actual features since that would make the code long, complicated, and more difficult to understand):

#include <iostream>

class MyVector {
private:
    int *_pbegin;
    int *_pend;
    int *_pcapacity;
public:
    MyVector() {
        _pbegin = new int;
        _pend = _pbegin;
        _pcapacity = _pbegin + 1;
    }

    ~MyVector() {
        delete _pbegin;
    }

    void reallocate(size_t newCapacity) {
        // Copy data into a temporary buffer
        size_t prevSize = size();
        int *prevData = new int[prevSize];
        memcpy(prevData, _pbegin, prevSize * sizeof(int));

        // Remove current data from memory and
        // reallocate the amount of available memory
        delete _pbegin;
        _pbegin = new int[newCapacity];
        _pend = _pbegin + prevSize;
        _pcapacity = _pbegin + newCapacity;

        //Copy previous data into the new memory
        memcpy(_pbegin, prevData, prevSize * sizeof(int));

        // Remove the temporary buffer from memory
        delete prevData;
    }

    void push(int value) {
        if (_pend == _pcapacity) {
            reallocate(capacity() * 2);
        }

        *_pend = value;
        _pend++;
    }

    int at(size_t pos) {
        return _pbegin[pos];
    }

    size_t size() {
        return _pend - _pbegin;
    }

    size_t capacity() {
        return _pcapacity - _pbegin;
    }
};

int main() {
    MyVector vec;
    
    std::cout << "Current size: " << vec.size() << std::endl;
    std::cout << "Current capacity: " << vec.capacity() << std::endl << std::endl;
    
    vec.push(42);

    std::cout << "Inserted one element..." << std::endl;
    std::cout << "Current size: " << vec.size() << std::endl;
    std::cout << "Current capacity: " << vec.capacity() << std::endl << std::endl;

    vec.push(1234);

    std::cout << "Inserted one element..." << std::endl;
    std::cout << "Current size: " << vec.size() << std::endl;
    std::cout << "Current capacity: " << vec.capacity() << std::endl << std::endl;
    
    vec.push(99);

    std::cout << "Inserted one element..." << std::endl;
    std::cout << "Current size: " << vec.size() << std::endl;
    std::cout << "Current capacity: " << vec.capacity() << std::endl << std::endl;
    
    vec.push(1);
    vec.push(500);

    std::cout << "Inserted two elements..." << std::endl;
    std::cout << "Current size: " << vec.size() << std::endl;
    std::cout << "Current capacity: " << vec.capacity() << std::endl << std::endl;

    std::cout << "Listing each element..." << std::endl;
    for (size_t i = 0; i < vec.size(); ++i) {
        printf("vec[%u] => %d\n", i, vec.at(i));
    }
    std::cout << std::endl;
}

Here's that code running on Ideone.com

At 1/26/14 02:16 PM, coln wrote: Speaking of that, what's the point of this (in both vectors and structs)? I see that vectors would use it to be a little more efficient, but why would structs need extra padding?

The reason vectors have capacity that increases exponentially is to lessen the amount of times that new capacity needs to be allocated, because that is an expensive operation. Each time the capacity is increased all the previous elements to be copied over, and, depending on the number of elements, that could take a while.

As for padding with structs: it's because some processors just require it (some don't). The struct could also be padded to place values in memory locations that are powers of two, which can make some operations more efficient. This page explains padding quite succinctly.

At 1/26/14 02:16 PM, coln wrote: I understand this, but where would you need to have efficient inserting over accessing? I am having difficulty thinking of an example where you wouldn't need to access the elements often.

A linked list would be useful for handling data that needs to be passed in FIFO (First In First Out) order, such as a message queue. As new messages arrive they can be inserted onto the end of the list, and as messages are processed they removed from the beginning of the list.

My EasyXInput framework, that I posted above, does exactly that for managing events by using the std::queue class, which is really just a linked list when you get down to it. There is no need to access any events in the middle of the queue/list, since it only makes sense to receive them in the order that they arrived.

Response to Programming Regs Lounge 2014-01-27 17:35:47


At 1/26/14 06:55 PM, Diki wrote: Here's that code running on Ideone.com

Gotta love ideone.com. Anyway, that makes much more sense then what I had in mind. And the pointers to calculate capacity and current size are ingenious.

The reason vectors have capacity that increases exponentially is to lessen the amount of times that new capacity needs to be allocated, because that is an expensive operation. Each time the capacity is increased all the previous elements to be copied over, and, depending on the number of elements, that could take a while.

Okay, in theory this will eventually run out of space, right? Let's say I want to add 65 elements, but I don't have 128 bytes of space available, I only have 100 (for some odd reason). Would vector fail to reallocate, therefore only allowing 64 elements?

As for padding with structs: it's because some processors just require it (some don't). The struct could also be padded to place values in memory locations that are powers of two, which can make some operations more efficient. This page explains padding quite succinctly.

That explains a lot. I didn't realize alignment was an issue in some systems.

A linked list would be useful for handling data that needs to be passed in FIFO (First In First Out) order, such as a message queue. As new messages arrive they can be inserted onto the end of the list, and as messages are processed they removed from the beginning of the list.

Ah interesting, okay.


BBS Signature

Response to Programming Regs Lounge 2014-01-27 18:32:15


At 1/27/14 05:35 PM, coln wrote: Gotta love ideone.com. Anyway, that makes much more sense then what I had in mind. And the pointers to calculate capacity and current size are ingenious.

That's because Dennis Ritchie, the man who designed C (and Unix, incidentally), was a very, very smart man. Pointer arithmetic in C++ is the same as C, and it makes working with memory so damned easy in both languages.

At 1/27/14 05:35 PM, coln wrote: Okay, in theory this will eventually run out of space, right? Let's say I want to add 65 elements, but I don't have 128 bytes of space available, I only have 100 (for some odd reason). Would vector fail to reallocate, therefore only allowing 64 elements?

In theory, yes. But if you were working on something with so little memory, such an embedded system, then you wouldn't want to be using a vector since the vector class itself uses up 32 bytes before any data is even added to it. With that little amount of memory your only real choice would be to just use arrays.

65 elements would also end up using more than 128 bytes (unless you were storing char elements). The capacity is just a measure of how many elements can be stored, so the memory used would be the product of capacity and the size of the type being stored. In my example I was storing integers, which will (probably) be four bytes in size, so 128 of them would require 512 bytes.

And if you attempted to add elements to a vector that would require more memory than is available the program would crash (assuming the OS has proper memory management, which it probably would).

Response to Programming Regs Lounge 2014-01-27 21:57:30


At 1/27/14 06:32 PM, Diki wrote: And if you attempted to add elements to a vector that would require more memory than is available the program would crash (assuming the OS has proper memory management, which it probably would).

Excuse me, I was assuming char elements. My example was rough, if that, but you answered my question. Man I love the control the programmer has in C/C++. It's almost scary :#


BBS Signature

Response to Programming Regs Lounge 2014-01-28 11:43:56


Dum dee dum dum, nobody posts code in here but me.

Got bored so I wrote a lottery simulator for the sake of laughing at how much money must be spent to eventually win the grand prize. I was going to write it in C for the hell of it, but then I remembered I would need to generate two sets of unique numbers, and compare them to see if each set contains the same numbers. Generating a set of unique integers would be trivial, but comparing two sets of unique integers with different ordering would be tedious, so I decided to use C++ instead since it has built-in functions to make that easy as pie.

Basically the logic I used was:

Step 1) Generate random integer.
    - If not found in ticket, add the number to the ticket.
    - If found, repeat Step 1.
    - If amount of numbers in ticket reaches desired amount go to Step 2.

Step 2) Sort ticket, generated in Step 1, from lowest to highest.

Step 3) Repeat Step 1 and Step 2 for the winning ticket.
    - When winning ticket is generated compare it to purchased ticket.
    - If not equal then discard winning ticket, and repeat Step 1 for winning ticket.
    - If equal then player has won the lottery (woohoo).

I set the program up to use the rules for the Lotto 6/49, which is a national lottery in Canada. The rules are you pick six numbers between one and 49, no repeats. There's also a bonus seventh number you can pick, but I didn't incorporate that. The odds of winning the Lotto 6/49 are 1 in 13,983,816 and that can be calculated with this simple equation:

v = amount of values to choose from (i.e. the upper limit)
n = amount of numbers that must be chosen

    !v
----------
!(v-n)!n

Which looks like this with the variables filled in according to the Lotto 6/49:

!49
----------
!(49-6)!6

Anyway, the source code is here (I decided to link it rather than post it because including that much code in a post really looks ugly without syntax highlighting). On average it takes my computer about eight to fifteen seconds to generate a winning ticket. I also stuck the entire thing in a constant loop to see how few tickets I could get it to win with, and the best I was able to get. After running it for a few minutes the best I got was around 4,000,000 tickets and the worst was around 77,000,000 tickets.

So if ever you needed a reason to not play the lottery, now you have one.

And now I'm bored again. Might take a crack at writing it in C for a little extra challenge.

Response to Programming Regs Lounge 2014-01-28 12:16:03


Took a crack at rewriting it in C and it turns out I was just overcomplicating it in my head. It was actually quite easy to write, even without using any built-in functions (other than srand(), rand(), time() and printf() of course, but those are kinda necessary).

Time to go back to being bored...

Response to Programming Regs Lounge 2014-01-30 17:02:37


At 1/28/14 12:16 PM, Diki wrote: Took a crack at rewriting it in C and it turns out I was just overcomplicating it in my head. It was actually quite easy to write, even without using any built-in functions (other than srand(), rand(), time() and printf() of course, but those are kinda necessary).

Any reason you chose size_t? I understand that it's an unsigned int with minimum of 16bits, but there is any advantage to using it over int? Are there concerns about int that size_t doesn't have?


BBS Signature

Response to Programming Regs Lounge 2014-01-30 19:18:32


At 1/30/14 05:02 PM, coln wrote: Any reason you chose size_t? I understand that it's an unsigned int with minimum of 16bits, but there is any advantage to using it over int? Are there concerns about int that size_t doesn't have?

size_t will most likely be 32 bits or 64 bits, depending on compiler settings. I would be surprised if you could get it to compile out to 16 bits on a modern system. If you're using MSVC v11, and possibly older versions of MSVC, size_t will be defined as the following (found in the crtdefs.h header):

#ifndef _SIZE_T_DEFINED
#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
#define _SIZE_T_DEFINED
#endif

On the version of GCC I have running through MinGW it is defined as (found in the stddef.h header):

#ifndef __SIZE_TYPE__
#define __SIZE_TYPE__ long unsigned int
#endif
#if !(defined (__GNUG__) && defined (size_t))
typedef __SIZE_TYPE__ size_t;
#ifdef __BEOS__
typedef long ssize_t;
#endif /* __BEOS__ */
#endif

So as far as functionality is concerned nothing is gained by using size_t since it's just an unsigned integer. It just makes it more clear what the value is representing, which is a good thing.

Response to Programming Regs Lounge 2014-01-30 21:26:15


At 1/30/14 07:18 PM, Diki wrote: So as far as functionality is concerned nothing is gained by using size_t since it's just an unsigned integer. It just makes it more clear what the value is representing, which is a good thing.

Use a type that reflects what you're doing... makes sense.

I've picked up Thinking in C++ by Bruce Eckel, and I was wondering if it was any good to read, or if I should avoid it and look elsewhere.


BBS Signature

Response to Programming Regs Lounge 2014-01-30 21:31:46


At 1/28/14 11:43 AM, Diki wrote: So if ever you needed a reason to not play the lottery, now you have one.

And yet people still play it.

And now I'm bored again. Might take a crack at writing it in C for a little extra challenge.

You should write a program like this but for bingo


BBS Signature

Response to Programming Regs Lounge 2014-01-30 23:01:48


At 1/30/14 09:26 PM, coln wrote: I've picked up Thinking in C++ by Bruce Eckel, and I was wondering if it was any good to read, or if I should avoid it and look elsewhere.

I'm not familiar with it, so I can't really say. But I did a quick Google search and it's available for free from here, so you don't really have anything to lose. Some of those links appear to be dead, but this one works.

At 1/30/14 09:31 PM, coln wrote: And yet people still play it.

Most people are really bad at both math and statistics, so they don't understand just how unlikely it is that they will ever win the lottery. One way to visualise just how unlikely winning would be is to use playing cards. Take thirteen of the same suit, shuffle them, and place them face down on a table. Being able to pick the ace, have the cards be shuffled, and pick the ace again one-million times in a row is basically the same odds as winning the lottery (it's actually slightly better odds).

At 1/30/14 09:31 PM, coln wrote: You should write a program like this but for bingo

That would be an interesting challenge, but earlier today I started up a new project that will involve a TCP-based socket server in C++ which will be taking up a lot of my time. I'm curious to see how far I can push the performance of TCP sockets in a real-time application; my current goal is to get a working version of online multiplayer Pong up and running. UDP sockets are better suited for real-time applications, but ultimately I intend to use the server for turn-based games and applications, so I'm sticking with TCP for now.

I did manage to get a proof of concept working with the server written in Python and the client in AS3 (compiled for Flash Player) but it only ran smoothly with two clients connected; any more and there was very noticeable lag. So I'm in the process of porting over this really, really awful Python code (seriously it's bad) to C++ with the boost::asio library. I also won't be hacking everything together like I did the Python code, since that was just a proof of concept, whereas I want this to actually be something usable.

I'll probably be posting updates on that as it progresses, but right now I'm still learning the inner-workings of the boost library, so I don't have anything to post (other than what currently basically amounts to an echo server).

Response to Programming Regs Lounge 2014-01-31 11:19:43


At 1/30/14 11:01 PM, Diki wrote: Most people are really bad at both math and statistics, so they don't understand just how unlikely it is that they will ever win the lottery. One way to visualise just how unlikely winning would be is to use playing cards. Take thirteen of the same suit, shuffle them, and place them face down on a table. Being able to pick the ace, have the cards be shuffled, and pick the ace again one-million times in a row is basically the same odds as winning the lottery (it's actually slightly better odds).

I may not understand the stated situation correctly, but the chances of winning the lottery are much higher than 1 out of 13^1000000.


BBS Signature

Response to Programming Regs Lounge 2014-01-31 14:02:40


At 1/31/14 11:19 AM, Tree-SkyLark-BCE wrote: I may not understand the stated situation correctly, but the chances of winning the lottery are much higher than 1 out of 13^1000000.

Indeed. I was tired when I thought up that hypothetical situation, and forgot that the odds picking the ace sequentially will increase exponentially, which makes what I said rather ironic. Oh well.

Response to Programming Regs Lounge 2014-02-02 18:43:30


At 1/30/14 11:01 PM, Diki wrote: I'll probably be posting updates on that as it progresses, but right now I'm still learning the inner-workings of the boost library, so I don't have anything to post (other than what currently basically amounts to an echo server).

Time for an update (and another wall of text).

I've been doing a lot of reading and tinkering, and I've gotten to the point that I'm comfortable working with Boost's Asio library. I used this example as a basic template for my code, and after tweaking the formatting to my preferences, and inserting the necessary functionality for communicating with Flash Player via sockets (e.g. responding to the cross-domain policy request) I now have this working code. It's still a proof of concept which is why I have it all in one file instead of separated into header and source files. The implementation is the same as the example found on Boost's website that I linked:

int main() {
    try {
        boost::asio::io_service io_service;
        Server server(io_service);
        io_service.run();
    } catch (std::exception& e) {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

And here's a breakdown of how it works:

After the server object is initialised it calls the start_accept() function, which allocates memory for a new client. When a client connection is called the handle_accept() function is called because of this line:

__acceptor.async_accept(pclient->socket(),
    boost::bind(&Server::handle_accept, this,
        pclient,
        boost::asio::placeholders::error
    )
);

Without going into too much detail, that is simply waiting for a connection on the socket object that is returned by pclient->socket(), and calls the callback, which is the second argument. The boost::bind function is kind of like a function pointer. The first argument to boost::bind() is the function that will be called, the second argument is a pointer to the object that holds the function, and the last two arguments are what will be passed to Server::handle_accept(). The Server::handle_accept() function simply initialises the client object, and tells it to start listening for incoming data, and then tells the server to once again listen for incoming connections.

The client listens for incoming data by this function being called:

inline void socket_read(size_t nbytes) {
    boost::asio::async_read(__socket, boost::asio::buffer(__data,nbytes),
        boost::bind(&Client::handle_read, shared_from_this(),
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred
        )
    );
}

It works pretty much the same way that async_accept() does. There are really only two notable differences. The first is that the second argument is boost::asio::buffer(__data,nbytes), which returns a buffer object that will store its data inside the __data variable (which is a char array) and expects the data to be of size nbytes. The second difference is the shared_from_this() function. It is used to return a pointer to the current object. The this pointer could technically be used there, but since the client object was allocated on the heap and stored in a shared_ptr object, that function must be used so that the Boost library knows that a reference to the pointer still exists, otherwise it could be popped off the heap. The shared_from_this() function exists because the Client class extends boost::enable_shared_from_this.

Once the socket receives data that is of size equal to or greater than nbytes it will call the Client::handle_read function that simply determines what type of data has been sent (i.e. either a header or a message). Because of the nature of Boost.Asio, and socket programming in C/C++ in general, you need to know how much data is going to be received before you receive it. I have it setup such that ever header message is 22 bytes and is in the format "NNP/1.0 LENGTH=125". It is unlikely that the header will ever actually be 22 bytes in size, so if it's not I simply pad the data until it is. The length determines the size of the message that will follow the header. NNP/1.0 stands for "NoName Protocol version 1.0", which is just a working title until I can think of something proper to put there.

So if I wanted to send "hello world" to the server I would first send:

NNP/1.0 LENGTH=11\0\0\0\0\0

And then immediately afterwards send:

hello world

Since the server received the header it knew that a message that is 11 bytes in size will follow. After receiving that message the server then listens for another piece of data that is 22 bytes in size, which will be another header.

One might wonder why I specifically chose to have a header size that is 22 bytes. The reason is that when Flash Player connects to a server over a socket that is hosted on a different domain than what Flash Player is running on it sends a policy request before anything else. The policy request is just the text "<policy-file-request/>", which is 22 bytes. After receiving a response to that request it disconnects the socket that that data was sent on, and opens a new one. Since I have no way of having Flash Player send a header before sending that policy request I opted to use 22 bytes as my header size for two reasons. Firstly 22 bytes is more than enough to store the necessary header information that I require. Secondly it's much simpler than trying to treat the policy request as some sort of special message. I could use the async_read_until() function, but it has the caveat of possibly receiving extra data after the specified delimiter, which would need to be parsed out. It made much more sense to just treat the policy request as a regular message and simply put an if statement in the handle_read() function:

void handle_read_message(size_t nbytes) {
	if (memcmp(__data, POLICY_REQUEST, POLICYREQUEST_LEN) == 0) {
		socket_write(POLICY, POLICY_LEN);
	}

	socket_read(PROTOHEAD_BUFFER_LEN);
}

I intend to write some code to optimise that function call such that it won't call memcmp() unless it's necessary to do so (i.e. only if it's possible for the data that has been received to be a policy request).

And that's pretty much it.

I haven't fully recreated the proof of concept that I wrote with my crappy Python server since the protocol I'm using for this C++ server is significantly different, but now that I have all the connecting/disconnecting and sending/receiving functionality coded in that won't really be that hard.

I hope someone actually reads this post because it took me like 40 minutes to write. ;(

Response to Programming Regs Lounge 2014-02-03 16:28:47


At 2/3/14 02:51 PM, FistofGreedo wrote: does anyone here ever used/tried LOLCODE ?
I'm currently learning it rather an awkward language if I do say so myself

I've never used it or tried to learn it, but I do know it being awkward is the point. It's an esoteric language, like Brainfuck. It's a lot more readable than Brainfuck, though, which truly lives up to its name.

Response to Programming Regs Lounge 2014-02-03 16:42:02


I see your LOLCODE hello world and raise you Brainfuck's:

+++++ +++++
[
    > +++++ ++
    > +++++ +++++
    > +++
    > +
    <<<< -
]
> ++ .
> + .
+++++ ++ .
.
+++ .
> ++ .
<< +++++ +++++ +++++ .
> .
+++ .
----- - .
----- --- .
> + .
> .

I know how it works (for the most part) and I still can't wrap my head around that syntax.

Response to Programming Regs Lounge 2014-02-04 13:53:22


Hey guys. Been a while since I last posted in here.

Since I last posted I was offered 3 different jobs: Analyst Programmer, Applications Support Analyst and IT Support Assistant. I went with the IT support role, for a few reasons. Mostly because I've always been unsure if programming 40 hours a week is something I could cope with and I'm still convinced that I wouldn't enjoy it. Plus, I've always been interested in picking up random bits of knowledge about computing so an IT support role definitely seemed like a great learning experience. Been there about a month now and definitely feel like I made the right decision. The guys I'm working with are great and it seems like the kind of job I'll enjoy. So far there haven't been any mornings where I've dreaded the thought of going to work.

Anyway, its been a while since I last did any programming but I'm not wanting to lose that skill altogether. I'm hoping that I can come up with a few little projects that I can tinker with now and then so that I don't get too rusty. Problem is, as usual, I'm struggling to come up with any ideas.

I decided to order myself a Raspberry Pi with the intention of using it to act as a server for any client/server projects I come up with, which is something I'd like to play around with. Also because I wanted to try and better familiarize myself with the Linux environment, and it seemed like a fun way of doing so for whatever reason. It's hard to explain why, but the Pi just seems like a nice little educational tool. In theory anyway. Still haven't received mine yet.

Right now I'm thinking I'll probably try writing a simple instant messaging server/client and have various people in my house running the client. In reality it's probably not that useful a project but ever since I was developing an ad-hoc audio chat application for my university dissertation I've wanted to have a go at developing something that required a server.

Web development is something I want to get back into too. A while back I was working on a website that me and a few other people thought would be useful but I ended up feeling like I bit off more than I could chew and struggled to remain motivated. I still don't have any ideas what I want to work on in relation to web development but hopefully I'll come up with some ideas.


BBS Moderator - Feel free to send me a PM if you have a problem!

BBS Signature

Response to Programming Regs Lounge 2014-02-04 20:17:41


At 2/4/14 01:53 PM, Dean wrote: Hey guys. Been a while since I last posted in here.

Nice to see another regular 'round these parts. :)

At 2/4/14 01:53 PM, Dean wrote: Since I last posted I was offered 3 different jobs: Analyst Programmer, Applications Support Analyst and IT Support Assistant. I went with the IT support role, for a few reasons. Mostly because I've always been unsure if programming 40 hours a week is something I could cope with and I'm still convinced that I wouldn't enjoy it.

Programming full-time can be pretty rough, that's for damn sure. I've pretty much always hated PHP, but at my last job I had to write it full-time and that made me absolutely loathe PHP, and dislike web development in general. All of my hobby projects now have little to nothing to do with web development as a result.

At 2/4/14 01:53 PM, Dean wrote: Web development is something I want to get back into too. A while back I was working on a website that me and a few other people thought would be useful but I ended up feeling like I bit off more than I could chew and struggled to remain motivated. I still don't have any ideas what I want to work on in relation to web development but hopefully I'll come up with some ideas.

Not to discourage you from doing web dev stuff, though. :)

Anyway, on to what I've been up to. A few posts up I described a server I am working on, and as of a few minutes ago I got the implementation of the WebSocket handshake protocol working.

Given that this is C++ it was rather tricky, and required a fair amount of reading and tinkering (as usual). Since C++, or the STL, has no way of splitting a string by delimiter I had to write a function to do that for me, as well as another function to use that to split the arguments of an HTTP request into a map. The source for those two functions is here. I still need to do some more thorough testing with them, and see if I can optimise them, but so far they work just fine.

The real trouble came with hashing the WebSocket key with SHA1, and base64 encoding the result of that. I ultimately had to use code written by other people, which I found on StackOverflow, to get that to work. The Boost libraries for SHA1 and base64 are very complex, so I need to do even more reading before I can hope to write my own functions for that (or optimise the ones that I found). The source for the two functions is here, which can be used to encode the WebSocket key with this tiny function. I ended up sticking all that into a utility header (i.e. just a header that will contain utility functions) of which the source code is here.

All that allows me to very easily parse an HTTP request into a class (source here) and encode the WebSocket key. Using my server code that I posted above, with some slight tweaks to make it work with HTTP, this is all the code required to allow a WebSocket connection.

Like before this is still just a proof of concept, which is why I'm building the response in such a cumbersome manner (among other things).

I also figure that there's no harm in explaining why I'm making all of this. I'm going to be using this server, and the JavaScript client outlined in this post, to create a web-based online hacking simulation game. It's a game inspired by Slavehack, Uplink and Hacker Evolution. I'm making the game web-based simply for the accessibility that it offers. Pretty much everything is going to be powered by WebSockets to allow for push-style updates and notifications, something that Slavehack is lacking. It will be much closer to Uplink and Hacker Evolution in style, but unlike those games it will be entirely multiplayer. I have no idea what I'm going to call it, but it has the working title "Trojan Bit".

Now that my server is progressing nicely it won't be long until I'll have something that is actually usable in web browsers. I still need to implement my protocol for sending/receiving messages over WebSocket, but that won't be very difficult considering I already have an implementation written in Python, so it's just a matter of translating the language.

Once I get my VPS setup, and all the required development tools installed on it, I'll have something up and running that people can actually use/test. For now everything is just running on my home computer, so I can't really leave a server running.