diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-02-09 22:10:30 -0300 |
commit | 0b806ee0fc9097fa7bda7ac0109191c9c5e0a1ac (patch) | |
tree | 276c4d099e178eb67fbd14f61d77b05e3808e9e3 /drivers/unix | |
parent | 0e49da1687bc8192ed210947da52c9e5c5f301bb (diff) |
GODOT IS OPEN SOURCE
Diffstat (limited to 'drivers/unix')
-rw-r--r-- | drivers/unix/SCsub | 7 | ||||
-rw-r--r-- | drivers/unix/dir_access_unix.cpp | 312 | ||||
-rw-r--r-- | drivers/unix/dir_access_unix.h | 88 | ||||
-rw-r--r-- | drivers/unix/file_access_unix.cpp | 257 | ||||
-rw-r--r-- | drivers/unix/file_access_unix.h | 81 | ||||
-rw-r--r-- | drivers/unix/ip_unix.cpp | 68 | ||||
-rw-r--r-- | drivers/unix/ip_unix.h | 49 | ||||
-rw-r--r-- | drivers/unix/memory_pool_static_malloc.cpp | 419 | ||||
-rw-r--r-- | drivers/unix/memory_pool_static_malloc.h | 82 | ||||
-rw-r--r-- | drivers/unix/mutex_posix.cpp | 73 | ||||
-rw-r--r-- | drivers/unix/mutex_posix.h | 61 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 410 | ||||
-rw-r--r-- | drivers/unix/os_unix.h | 121 | ||||
-rw-r--r-- | drivers/unix/semaphore_posix.cpp | 89 | ||||
-rw-r--r-- | drivers/unix/semaphore_posix.h | 62 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.cpp | 388 | ||||
-rw-r--r-- | drivers/unix/stream_peer_tcp_posix.h | 89 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.cpp | 178 | ||||
-rw-r--r-- | drivers/unix/tcp_server_posix.h | 57 | ||||
-rw-r--r-- | drivers/unix/thread_posix.cpp | 99 | ||||
-rw-r--r-- | drivers/unix/thread_posix.h | 75 |
21 files changed, 3065 insertions, 0 deletions
diff --git a/drivers/unix/SCsub b/drivers/unix/SCsub new file mode 100644 index 0000000000..bcd231579c --- /dev/null +++ b/drivers/unix/SCsub @@ -0,0 +1,7 @@ +Import('env') + +env.add_source_files(env.drivers_sources,"*.cpp") + +Export('env') + + diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp new file mode 100644 index 0000000000..fff86c5a7e --- /dev/null +++ b/drivers/unix/dir_access_unix.cpp @@ -0,0 +1,312 @@ +/*************************************************************************/ +/* dir_access_unix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "dir_access_unix.h" + +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) + +#ifndef ANDROID_ENABLED +#include <sys/statvfs.h> +#endif + +#include <stdio.h> +#include "os/memory.h" +#include "print_string.h" +#include <errno.h> + +DirAccess *DirAccessUnix::create_fs() { + + return memnew( DirAccessUnix ); +} + +bool DirAccessUnix::list_dir_begin() { + + list_dir_end(); //close any previous dir opening! + + +// char real_current_dir_name[2048]; //is this enough?! + //getcwd(real_current_dir_name,2048); + //chdir(curent_path.utf8().get_data()); + dir_stream = opendir(current_dir.utf8().get_data()); + //chdir(real_current_dir_name); + if (!dir_stream) + return true; //error! + + return false; +} + +bool DirAccessUnix::file_exists(String p_file) { + + GLOBAL_LOCK_FUNCTION + + + if (p_file.is_rel_path()) + p_file=current_dir+"/"+p_file; + else + p_file=fix_path(p_file); + + struct stat flags; + bool success = (stat(p_file.utf8().get_data(),&flags)==0); + + if (success && S_ISDIR(flags.st_mode)) { + success=false; + } + + return success; + +} + +uint64_t DirAccessUnix::get_modified_time(String p_file) { + + if (p_file.is_rel_path()) + p_file=current_dir+"/"+p_file; + else + p_file=fix_path(p_file); + + struct stat flags; + bool success = (stat(p_file.utf8().get_data(),&flags)==0); + + if (success) { + return flags.st_mtime; + } else { + + ERR_FAIL_V(0); + }; + return 0; +}; + + +String DirAccessUnix::get_next() { + + if (!dir_stream) + return ""; + dirent *entry; + + entry=readdir(dir_stream); + + if (entry==NULL) { + + list_dir_end(); + return ""; + } + + //typedef struct stat Stat; + struct stat flags; + + String fname; + if (fname.parse_utf8(entry->d_name)) + fname=entry->d_name; //no utf8, maybe latin? + + String f=current_dir+"/"+fname; + + if (stat(f.utf8().get_data(),&flags)==0) { + + if (S_ISDIR(flags.st_mode)) { + + _cisdir=true; + + } else { + + _cisdir=false; + } + + } else { + + _cisdir=false; + + } + + + + + return fname; + +} + +bool DirAccessUnix::current_is_dir() const { + + return _cisdir; +} + + +void DirAccessUnix::list_dir_end() { + + if (dir_stream) + closedir(dir_stream); + dir_stream=0; + _cisdir=false; +} + +int DirAccessUnix::get_drive_count() { + + return 0; +} +String DirAccessUnix::get_drive(int p_drive) { + + return ""; +} + +Error DirAccessUnix::make_dir(String p_dir) { + + GLOBAL_LOCK_FUNCTION + + p_dir=fix_path(p_dir); + + char real_current_dir_name[2048]; + getcwd(real_current_dir_name,2048); + chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants + + bool success=(mkdir(p_dir.utf8().get_data(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)==0); + int err = errno; + + chdir(real_current_dir_name); + + if (success) { + return OK; + }; + + if (err == EEXIST) { + return ERR_ALREADY_EXISTS; + }; + + return ERR_CANT_CREATE; +} + + +Error DirAccessUnix::change_dir(String p_dir) { + + GLOBAL_LOCK_FUNCTION + p_dir=fix_path(p_dir); + + + char real_current_dir_name[2048]; + getcwd(real_current_dir_name,2048); + String prev_dir; + if (prev_dir.parse_utf8(real_current_dir_name)) + prev_dir=real_current_dir_name; //no utf8, maybe latin? + + chdir(current_dir.utf8().get_data()); //ascii since this may be unicode or wathever the host os wants + bool worked=(chdir(p_dir.utf8().get_data())==0); // we can only give this utf8 +#ifndef IPHONE_ENABLED + String base = _get_root_path(); + if (base!="") { + + getcwd(real_current_dir_name,2048); + String new_dir; + new_dir.parse_utf8(real_current_dir_name); + if (!new_dir.begins_with(base)) + worked=false; + } +#endif + if (worked) { + + getcwd(real_current_dir_name,2048); + if (current_dir.parse_utf8(real_current_dir_name)) + current_dir=real_current_dir_name; //no utf8, maybe latin? + } + + chdir(prev_dir.utf8().get_data()); + return worked?OK:ERR_INVALID_PARAMETER; + +} + +String DirAccessUnix::get_current_dir() { + + String base = _get_root_path(); + if (base!="") { + + String bd = current_dir.replace_first(base,""); + if (bd.begins_with("/")) + return _get_root_string()+bd.substr(1,bd.length()); + else + return _get_root_string()+bd; + + } + return current_dir; +} + +Error DirAccessUnix::rename(String p_path,String p_new_path) { + + p_path=fix_path(p_path); + p_new_path=fix_path(p_new_path); + + return ::rename(p_path.utf8().get_data(),p_new_path.utf8().get_data())==0?OK:FAILED; +} +Error DirAccessUnix::remove(String p_path) { + + p_path=fix_path(p_path); + + struct stat flags; + if ((stat(p_path.utf8().get_data(),&flags)!=0)) + return FAILED; + + if (S_ISDIR(flags.st_mode)) + return ::rmdir(p_path.utf8().get_data())==0?OK:FAILED; + else + return ::unlink(p_path.utf8().get_data())==0?OK:FAILED; +} + + +size_t DirAccessUnix::get_space_left() { + +#ifndef NO_STATVFS + struct statvfs vfs; + if (statvfs(current_dir.utf8().get_data(), &vfs) != 0) { + + return -1; + }; + + return vfs.f_bfree * vfs.f_bsize; +#else +#warning THIS IS BROKEN + return 0; +#endif +}; + + + +DirAccessUnix::DirAccessUnix() { + + dir_stream=0; + current_dir="."; + _cisdir=false; + + /* determine drive count */ + + change_dir(current_dir); + +} + + +DirAccessUnix::~DirAccessUnix() { + + list_dir_end(); +} + + +#endif //posix_enabled diff --git a/drivers/unix/dir_access_unix.h b/drivers/unix/dir_access_unix.h new file mode 100644 index 0000000000..7ede4fc31c --- /dev/null +++ b/drivers/unix/dir_access_unix.h @@ -0,0 +1,88 @@ +/*************************************************************************/ +/* dir_access_unix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef DIR_ACCESS_UNIX_H +#define DIR_ACCESS_UNIX_H + +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <dirent.h> + +#include "os/dir_access.h" + + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class DirAccessUnix : public DirAccess { + + DIR *dir_stream; + + static DirAccess *create_fs(); + + String current_dir; + bool _cisdir; + +public: + + virtual bool list_dir_begin(); ///< This starts dir listing + virtual String get_next(); + virtual bool current_is_dir() const; + + virtual void list_dir_end(); ///< + + virtual int get_drive_count(); + virtual String get_drive(int p_drive); + + virtual Error change_dir(String p_dir); ///< can be relative or absolute, return false on success + virtual String get_current_dir(); ///< return current dir location + virtual Error make_dir(String p_dir); + + virtual bool file_exists(String p_file); + virtual uint64_t get_modified_time(String p_file); + + + + virtual Error rename(String p_from, String p_to); + virtual Error remove(String p_name); + + virtual size_t get_space_left(); + + + DirAccessUnix(); + ~DirAccessUnix(); + +}; + + + +#endif //UNIX ENABLED +#endif diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp new file mode 100644 index 0000000000..239e41be4c --- /dev/null +++ b/drivers/unix/file_access_unix.cpp @@ -0,0 +1,257 @@ +/*************************************************************************/ +/* file_access_unix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "file_access_unix.h" + +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) + +#include <sys/types.h> +#include <sys/stat.h> +#include "print_string.h" +#include "core/os/os.h" + +#ifndef ANDROID_ENABLED +#include <sys/statvfs.h> +#endif + +#ifdef MSVC + #define S_ISREG(m) ((m)&_S_IFREG) +#endif +#ifndef S_ISREG + #define S_ISREG(m) ((m) & S_IFREG) +#endif + +void FileAccessUnix::check_errors() const { + + ERR_FAIL_COND(!f); + + if (feof(f)) { + + last_error=ERR_FILE_EOF; + } + +} + +Error FileAccessUnix::_open(const String& p_path, int p_mode_flags) { + + if (f) + fclose(f); + f=NULL; + + String path=fix_path(p_path); + //printf("opening %ls\n", path.c_str()); + + ERR_FAIL_COND_V(f,ERR_ALREADY_IN_USE); + const char* mode_string; + + if (p_mode_flags==READ) + mode_string="rb"; + else if (p_mode_flags==WRITE) + mode_string="wb"; + else if (p_mode_flags==READ_WRITE) + mode_string="wb+"; + else + return ERR_INVALID_PARAMETER; + + /* pretty much every implementation that uses fopen as primary + backend (unix-compatible mostly) supports utf8 encoding */ + + //printf("opening %s as %s\n", p_path.utf8().get_data(), path.utf8().get_data()); + struct stat st; + if (stat(path.utf8().get_data(),&st) == 0) { + + if (!S_ISREG(st.st_mode)) + return ERR_FILE_CANT_OPEN; + + }; + + if (is_backup_save_enabled() && p_mode_flags&WRITE && !(p_mode_flags&READ)) { + save_path=path; + path=path+".tmp"; + //print_line("saving instead to "+path); + } + + f=fopen(path.utf8().get_data(),mode_string); + + if (f==NULL) { + last_error=ERR_FILE_CANT_OPEN; + return ERR_FILE_CANT_OPEN; + } else { + last_error=OK; + flags=p_mode_flags; + return OK; + } + +} +void FileAccessUnix::close() { + + if (!f) + return; + fclose(f); + f = NULL; + if (save_path!="") { + + //unlink(save_path.utf8().get_data()); + //print_line("renaming.."); + int rename_error = rename((save_path+".tmp").utf8().get_data(),save_path.utf8().get_data()); + save_path=""; + ERR_FAIL_COND( rename_error != 0); + } + + +} +bool FileAccessUnix::is_open() const{ + + return (f!=NULL); +} +void FileAccessUnix::seek(size_t p_position) { + + ERR_FAIL_COND(!f); + + last_error=OK; + if ( fseek(f,p_position,SEEK_SET) ) + check_errors(); +} +void FileAccessUnix::seek_end(int64_t p_position) { + + ERR_FAIL_COND(!f); + if ( fseek(f,p_position,SEEK_END) ) + check_errors(); +} +size_t FileAccessUnix::get_pos() const{ + + + size_t aux_position=0; + if ( !(aux_position = ftell(f)) ) { + check_errors(); + }; + return aux_position; +} +size_t FileAccessUnix::get_len() const{ + + + ERR_FAIL_COND_V(!f,0); + + FileAccessUnix *fau = const_cast<FileAccessUnix*>(this); + int pos = fau->get_pos(); + fau->seek_end(); + int size = fau->get_pos(); + fau->seek(pos); + + return size; +} + +bool FileAccessUnix::eof_reached() const{ + + return last_error==ERR_FILE_EOF; +} + +uint8_t FileAccessUnix::get_8() const{ + + ERR_FAIL_COND_V(!f,0); + uint8_t b; + if (fread(&b,1,1,f) == 0) { + check_errors(); + }; + + return b; +} + +int FileAccessUnix::get_buffer(uint8_t *p_dst, int p_length) const { + + ERR_FAIL_COND_V(!f,-1); + int read = fread(p_dst, 1, p_length, f); + check_errors(); + return read; +}; + +Error FileAccessUnix::get_error() const{ + + return last_error; +} + +void FileAccessUnix::store_8(uint8_t p_dest) { + + ERR_FAIL_COND(!f); + fwrite(&p_dest,1,1,f); + +} + + +bool FileAccessUnix::file_exists(const String &p_path) { + + FILE *g; + //printf("opening file %s\n", p_fname.c_str()); + String filename=fix_path(p_path); + g=fopen(filename.utf8().get_data(),"rb"); + if (g==NULL) { + + return false; + } else { + + fclose(g); + return true; + } +} + +uint64_t FileAccessUnix::_get_modified_time(const String &p_file) { + + String file=fix_path(p_file); + struct stat flags; + bool success = (stat(file.utf8().get_data(),&flags)==0); + + if (success) { + return flags.st_mtime; + } else { + print_line("ERROR IN: "+p_file); + + ERR_FAIL_V(0); + }; + +} + +FileAccess * FileAccessUnix::create_libc() { + + return memnew( FileAccessUnix ); +} + + +FileAccessUnix::FileAccessUnix() { + + f=NULL; + flags=0; + last_error=OK; + +} +FileAccessUnix::~FileAccessUnix() { + + close(); + +} + +#endif diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h new file mode 100644 index 0000000000..0dedfce6ac --- /dev/null +++ b/drivers/unix/file_access_unix.h @@ -0,0 +1,81 @@ +/*************************************************************************/ +/* file_access_unix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef FILE_ACCESS_UNIX_H +#define FILE_ACCESS_UNIX_H + +#include "os/file_access.h" +#include "os/memory.h" +#include <stdio.h> + +#if defined(UNIX_ENABLED) || defined(LIBC_FILEIO_ENABLED) + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class FileAccessUnix : public FileAccess { + + FILE *f; + int flags; + void check_errors() const; + mutable Error last_error; + String save_path; + + static FileAccess* create_libc(); +public: + + virtual Error _open(const String& p_path, int p_mode_flags); ///< open a file + virtual void close(); ///< close a file + virtual bool is_open() const; ///< true when file is open + + virtual void seek(size_t p_position); ///< seek to a given position + virtual void seek_end(int64_t p_position=0); ///< seek from the end of file + virtual size_t get_pos() const; ///< get position in the file + virtual size_t get_len() const; ///< get size of the file + + virtual bool eof_reached() const; ///< reading passed EOF + + virtual uint8_t get_8() const; ///< get a byte + virtual int get_buffer(uint8_t *p_dst, int p_length) const; + + virtual Error get_error() const; ///< get last error + + virtual void store_8(uint8_t p_dest); ///< store a byte + + virtual bool file_exists(const String& p_path); ///< return true if a file exists + + virtual uint64_t _get_modified_time(const String& p_file); + + FileAccessUnix(); + virtual ~FileAccessUnix(); + +}; + + +#endif +#endif diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp new file mode 100644 index 0000000000..c11426d356 --- /dev/null +++ b/drivers/unix/ip_unix.cpp @@ -0,0 +1,68 @@ +/*************************************************************************/ +/* ip_unix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "ip_unix.h" + +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) + +#ifdef WINDOWS_ENABLED +#include <ws2tcpip.h> +#include <winsock2.h> +#include <windows.h> +#else +#include <netdb.h> +#endif +IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { + + struct hostent *he; + if ((he=gethostbyname(p_hostname.utf8().get_data())) == NULL) { // get the host info + ERR_PRINT("gethostbyname failed!"); + return IP_Address(); + } + IP_Address ip; + + ip.host= *((unsigned long*)he->h_addr); + + return ip; + +} + +void IP_Unix::make_default() { + + _create=_create_unix; +} + +IP* IP_Unix::_create_unix() { + + return memnew( IP_Unix ); +} + +IP_Unix::IP_Unix() { +} + +#endif diff --git a/drivers/unix/ip_unix.h b/drivers/unix/ip_unix.h new file mode 100644 index 0000000000..ec2d42c837 --- /dev/null +++ b/drivers/unix/ip_unix.h @@ -0,0 +1,49 @@ +/*************************************************************************/ +/* ip_unix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef IP_UNIX_H +#define IP_UNIX_H + +#include "io/ip.h" + +#if defined(UNIX_ENABLED) || defined(WINDOWS_ENABLED) + +class IP_Unix : public IP { + OBJ_TYPE(IP_Unix, IP); + + virtual IP_Address _resolve_hostname(const String& p_hostname); + + static IP* _create_unix(); +public: + + static void make_default(); + IP_Unix(); +}; + +#endif +#endif // IP_UNIX_H diff --git a/drivers/unix/memory_pool_static_malloc.cpp b/drivers/unix/memory_pool_static_malloc.cpp new file mode 100644 index 0000000000..fa1266b2df --- /dev/null +++ b/drivers/unix/memory_pool_static_malloc.cpp @@ -0,0 +1,419 @@ +/*************************************************************************/ +/* memory_pool_static_malloc.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "memory_pool_static_malloc.h" +#include "error_macros.h" +#include "os/memory.h" +#include <stdlib.h> +#include <stdio.h> +#include "os/copymem.h" +#include "os/os.h" + +/** + * NOTE NOTE NOTE NOTE + * in debug mode, this prepends the memory size to the allocated block + * so BE CAREFUL! + */ + + +void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) { + + #if DFAULT_ALIGNMENT == 1 + + return _alloc(p_bytes, p_description); + + #else + + int total = p_bytes + DEFAULT_ALIGNMENT; + uint8_t* ptr = (uint8_t*)_alloc(total, p_description); + ERR_FAIL_COND_V( !ptr, ptr ); + int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1))); + ptr[ofs-1] = ofs; + return (void*)(ptr + ofs); + #endif +}; + +void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) { + + ERR_FAIL_COND_V(p_bytes==0,0); + + MutexLock lock(mutex); + +#ifdef DEBUG_MEMORY_ENABLED + void *mem=malloc(p_bytes+sizeof(RingPtr)); /// add for size and ringlist + + if (!mem) { + printf("**ERROR: out of memory while allocating %i bytes by %s?\n",(int) p_bytes, p_description); + printf("**ERROR: memory usage is %i\n", (int)get_total_usage()); + }; + + ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request + + /* setup the ringlist element */ + + RingPtr *ringptr = (RingPtr*)mem; + + /* setup the ringlist element data (description and size ) */ + + ringptr->size = p_bytes; + ringptr->descr=p_description; + + if (ringlist) { /* existing ringlist */ + + /* assign next */ + ringptr->next = ringlist->next; + ringlist->next = ringptr; + /* assign prev */ + ringptr->prev = ringlist; + ringptr->next->prev = ringptr; + } else { /* non existing ringlist */ + + ringptr->next=ringptr; + ringptr->prev=ringptr; + ringlist=ringptr; + + } + + total_mem+=p_bytes; + + /* update statistics */ + if (total_mem > max_mem ) + max_mem = total_mem; + + total_pointers++; + + if (total_pointers > max_pointers) + max_pointers=total_pointers; + + return ringptr + 1; /* return memory after ringptr */ + +#else + void *mem=malloc(p_bytes); + + ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request + return mem; +#endif +} + + +void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) { + + #if DFAULT_ALIGNMENT == 1 + + return _realloc(p_memory,p_bytes); + #else + if (!p_memory) + return alloc(p_bytes); + + int total = p_bytes + DEFAULT_ALIGNMENT; + uint8_t* mem = (uint8_t*)p_memory; + int ofs = *(mem-1); + mem = mem - ofs; + uint8_t* ptr = (uint8_t*)_realloc(mem, total); + ERR_FAIL_COND_V(ptr == NULL, NULL); + int new_ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1))); + if (new_ofs != ofs) { + + //printf("realloc moving %i bytes\n", p_bytes); + movemem((ptr + new_ofs), (ptr + ofs), p_bytes); + ptr[new_ofs-1] = new_ofs; + }; + return ptr + new_ofs; + #endif +}; + +void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) { + + if (p_memory==NULL) { + + return alloc( p_bytes ); + } + + if (p_bytes<=0) { + + this->free(p_memory); + ERR_FAIL_COND_V( p_bytes < 0 , NULL ); + return NULL; + } + + MutexLock lock(mutex); + +#ifdef DEBUG_MEMORY_ENABLED + + + RingPtr *ringptr = (RingPtr*)p_memory; + ringptr--; /* go back an element to find the tingptr */ + + bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr); + bool is_list = ( ringlist == ringptr ); + + + RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr)); + + ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed + + /* actualize mem used */ + total_mem -= new_ringptr->size; + new_ringptr->size = p_bytes; + total_mem += new_ringptr->size; + + if (total_mem > max_mem ) //update statistics + max_mem = total_mem; + + if (new_ringptr == ringptr ) + return ringptr + 1; // block didn't move, don't do anything + + if (single_element) { + + new_ringptr->next=new_ringptr; + new_ringptr->prev=new_ringptr; + } else { + + new_ringptr->next->prev=new_ringptr; + new_ringptr->prev->next=new_ringptr; + } + + if (is_list) + ringlist=new_ringptr; + + + return new_ringptr + 1; + +#else + return ::realloc( p_memory, p_bytes ); +#endif +} + +void MemoryPoolStaticMalloc::free(void *p_ptr) { + + ERR_FAIL_COND( !MemoryPoolStatic::get_singleton()); + + #if DFAULT_ALIGNMENT == 1 + + _free(p_ptr); + #else + + uint8_t* mem = (uint8_t*)p_ptr; + int ofs = *(mem-1); + mem = mem - ofs; + + _free(mem); + #endif +}; + + +void MemoryPoolStaticMalloc::_free(void *p_ptr) { + + MutexLock lock(mutex); + +#ifdef DEBUG_MEMORY_ENABLED + + if (p_ptr==0) { + printf("**ERROR: STATIC ALLOC: Attempted free of NULL pointer.\n"); + return; + }; + + RingPtr *ringptr = (RingPtr*)p_ptr; + + ringptr--; /* go back an element to find the ringptr */ + + +#if 0 + { // check for existing memory on free. + RingPtr *p = ringlist; + + bool found=false; + + if (ringlist) { + do { + if (p==ringptr) { + found=true; + break; + } + + p=p->next; + } while (p!=ringlist); + } + + if (!found) { + printf("**ERROR: STATIC ALLOC: Attempted free of unknown pointer at %p\n",(ringptr+1)); + return; + } + + } +#endif + /* proceed to erase */ + + bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr); + bool is_list = ( ringlist == ringptr ); + + if (single_element) { + /* just get rid of it */ + ringlist=0; + + } else { + /* auto-remove from ringlist */ + if (is_list) + ringlist=ringptr->next; + + ringptr->prev->next = ringptr->next; + ringptr->next->prev = ringptr->prev; + } + + total_mem -= ringptr->size; + total_pointers--; + // catch more errors + zeromem(ringptr,sizeof(RingPtr)+ringptr->size); + ::free(ringptr); //just free that pointer + +#else + ERR_FAIL_COND(p_ptr==0); + + ::free(p_ptr); +#endif +} + + +size_t MemoryPoolStaticMalloc::get_available_mem() const { + + return 0xffffffff; +} + +size_t MemoryPoolStaticMalloc::get_total_usage() { + +#ifdef DEBUG_MEMORY_ENABLED + + return total_mem; +#else + return 0; +#endif + +} + +size_t MemoryPoolStaticMalloc::get_max_usage() { + + return max_mem; +} + +/* Most likely available only if memory debugger was compiled in */ +int MemoryPoolStaticMalloc::get_alloc_count() { + + return 0; +} +void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) { + + return 0; +} +const char* MemoryPoolStaticMalloc::get_alloc_description(int p_alloc_idx) { + + + return ""; +} +size_t MemoryPoolStaticMalloc::get_alloc_size(int p_alloc_idx) { + + return 0; +} + +void MemoryPoolStaticMalloc::dump_mem_to_file(const char* p_file) { + +#ifdef DEBUG_MEMORY_ENABLED + + ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */ + RingPtr *p = ringlist; + FILE *f = fopen(p_file,"wb"); + + do { + fprintf(f,"%p-%i-%s\n", p+1, (int)p->size, (p->descr?p->descr:"") ); + p=p->next; + } while (p!=ringlist); + + fclose(f); +#endif + +} + +MemoryPoolStaticMalloc::MemoryPoolStaticMalloc() { + +#ifdef DEBUG_MEMORY_ENABLED + total_mem=0; + total_pointers=0; + ringlist=0; + max_mem=0; + max_pointers=0; + + +#endif + + mutex=NULL; +#ifndef NO_THREADS + + mutex=Mutex::create(); // at this point, this should work +#endif + +} + + +MemoryPoolStaticMalloc::~MemoryPoolStaticMalloc() { + + Mutex *old_mutex=mutex; + mutex=NULL; + if (old_mutex) + memdelete(old_mutex); + +#ifdef DEBUG_MEMORY_ENABLED + + if (OS::get_singleton()->is_stdout_verbose()) { + if (total_mem > 0 ) { + printf("**ERROR: STATIC ALLOC: ** MEMORY LEAKS DETECTED **\n"); + printf("**ERROR: STATIC ALLOC: %i bytes of memory in use at exit.\n",(int)total_mem); + + if (1){ + printf("**ERROR: STATIC ALLOC: Following is the list of leaked allocations: \n"); + + ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */ + RingPtr *p = ringlist; + + do { + printf("\t%p - %i bytes - %s\n", (RingPtr*)(p+1), (int)p->size, (p->descr?p->descr:"") ); + p=p->next; + } while (p!=ringlist); + + printf("**ERROR: STATIC ALLOC: End of Report.\n"); + }; + + printf("mem - max %i, pointers %i, leaks %i.\n",(int)max_mem,max_pointers,(int)total_mem); + } else { + + printf("INFO: mem - max %i, pointers %i, no leaks.\n",(int)max_mem,max_pointers); + } + } + +#endif +} + + diff --git a/drivers/unix/memory_pool_static_malloc.h b/drivers/unix/memory_pool_static_malloc.h new file mode 100644 index 0000000000..626fec826e --- /dev/null +++ b/drivers/unix/memory_pool_static_malloc.h @@ -0,0 +1,82 @@ +/*************************************************************************/ +/* memory_pool_static_malloc.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef MEMORY_POOL_STATIC_MALLOC_H +#define MEMORY_POOL_STATIC_MALLOC_H + +#include "os/memory_pool_static.h" +#include "os/mutex.h" +/** + @author Juan Linietsky <red@lunatea> +*/ +class MemoryPoolStaticMalloc : public MemoryPoolStatic { + + struct RingPtr { + + size_t size; + const char *descr; /* description of memory */ + RingPtr *next; + RingPtr *prev; + }; + + RingPtr *ringlist; + size_t total_mem; + int total_pointers; + + size_t max_mem; + int max_pointers; + + Mutex *mutex; + + void* _alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello" + void* _realloc(void *p_memory,size_t p_bytes); ///< Pointer in + void _free(void *p_ptr); ///< Pointer in p_description shold be to a const char const + +public: + + virtual void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello" + virtual void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const + virtual void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in + virtual size_t get_available_mem() const; + virtual size_t get_total_usage(); + virtual size_t get_max_usage(); + + /* Most likely available only if memory debugger was compiled in */ + virtual int get_alloc_count(); + virtual void * get_alloc_ptr(int p_alloc_idx); + virtual const char* get_alloc_description(int p_alloc_idx); + virtual size_t get_alloc_size(int p_alloc_idx); + + void dump_mem_to_file(const char* p_file); + + MemoryPoolStaticMalloc(); + ~MemoryPoolStaticMalloc(); + +}; + +#endif diff --git a/drivers/unix/mutex_posix.cpp b/drivers/unix/mutex_posix.cpp new file mode 100644 index 0000000000..166dfa4b19 --- /dev/null +++ b/drivers/unix/mutex_posix.cpp @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* mutex_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "mutex_posix.h" +#include "os/memory.h" + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +void MutexPosix::lock() { + + pthread_mutex_lock(&mutex); + +} +void MutexPosix::unlock() { + + pthread_mutex_unlock(&mutex); +} +Error MutexPosix::try_lock() { + + return (pthread_mutex_trylock(&mutex)==0)?OK:ERR_BUSY; +} + +Mutex *MutexPosix::create_func_posix(bool p_recursive) { + + return memnew( MutexPosix(p_recursive) ); +} + +void MutexPosix::make_default() { + + create_func=create_func_posix; +} + +MutexPosix::MutexPosix(bool p_recursive) { + + pthread_mutexattr_init(&attr); + if (p_recursive) + pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&mutex,&attr); +} + + +MutexPosix::~MutexPosix() { + + pthread_mutex_destroy(&mutex); +} + + +#endif diff --git a/drivers/unix/mutex_posix.h b/drivers/unix/mutex_posix.h new file mode 100644 index 0000000000..3496473688 --- /dev/null +++ b/drivers/unix/mutex_posix.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* mutex_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef MUTEX_POSIX_H +#define MUTEX_POSIX_H + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +#include <pthread.h> +#include "os/mutex.h" + +class MutexPosix : public Mutex { + + pthread_mutexattr_t attr; + pthread_mutex_t mutex; + + static Mutex *create_func_posix(bool p_recursive); + +public: + + virtual void lock(); + virtual void unlock(); + virtual Error try_lock(); + + + static void make_default(); + + MutexPosix(bool p_recursive); + + ~MutexPosix(); + +}; + +#endif + +#endif diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp new file mode 100644 index 0000000000..f684c63b3b --- /dev/null +++ b/drivers/unix/os_unix.cpp @@ -0,0 +1,410 @@ +/*************************************************************************/ +/* os_unix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "os_unix.h" + +#ifdef UNIX_ENABLED + +#include "memory_pool_static_malloc.h" +#include "os/memory_pool_dynamic_static.h" +#include "thread_posix.h" +#include "semaphore_posix.h" +#include "mutex_posix.h" +#include "core/os/thread_dummy.h" + +//#include "core/io/file_access_buffered_fa.h" +#include "file_access_unix.h" +#include "dir_access_unix.h" +#include "tcp_server_posix.h" +#include "stream_peer_tcp_posix.h" + + +#include <stdarg.h> +#include <sys/time.h> +#include <sys/wait.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> +#include <poll.h> +#include <errno.h> +#include <assert.h> +#include "globals.h" +void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type) { + + if (p_rationale && p_rationale[0]) { + + print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_rationale); + print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line); + + } else { + print("\E[1;31;40mERROR: %s: \E[1;37;40m%s\n",p_function,p_code); + print("\E[0;31;40m At: %s:%i.\E[0;0;37m\n",p_file,p_line); + + } +} + + +void OS_Unix::debug_break() { + + assert(false); +}; + +int OS_Unix::get_audio_driver_count() const { + + return 1; + +} +const char * OS_Unix::get_audio_driver_name(int p_driver) const { + + return "dummy"; +} + +int OS_Unix::unix_initialize_audio(int p_audio_driver) { + + return 0; +} + +static MemoryPoolStaticMalloc *mempool_static=NULL; +static MemoryPoolDynamicStatic *mempool_dynamic=NULL; + + +void OS_Unix::initialize_core() { + +#ifdef NO_PTHREADS + ThreadDummy::make_default(); + SemaphoreDummy::make_default(); + MutexDummy::make_default(); +#else + ThreadPosix::make_default(); + SemaphorePosix::make_default(); + MutexPosix::make_default(); +#endif + FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_RESOURCES); + FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_USERDATA); + FileAccess::make_default<FileAccessUnix>(FileAccess::ACCESS_FILESYSTEM); + //FileAccessBufferedFA<FileAccessUnix>::make_default(); + DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_RESOURCES); + DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_USERDATA); + DirAccess::make_default<DirAccessUnix>(DirAccess::ACCESS_FILESYSTEM); + +#ifndef NO_NETWORK + TCPServerPosix::make_default(); + StreamPeerTCPPosix::make_default(); + IP_Unix::make_default(); +#endif + mempool_static = new MemoryPoolStaticMalloc; + mempool_dynamic = memnew( MemoryPoolDynamicStatic ); + + ticks_start=0; + ticks_start=get_ticks_usec(); +} + +void OS_Unix::finalize_core() { + + + if (mempool_dynamic) + memdelete( mempool_dynamic ); + if (mempool_static) + delete mempool_static; + +} + + +void OS_Unix::vprint(const char* p_format, va_list p_list,bool p_stder) { + + if (p_stder) { + + vfprintf(stderr,p_format,p_list); + fflush(stderr); + } else { + + vprintf(p_format,p_list); + fflush(stdout); + } +} + +void OS_Unix::print(const char *p_format, ... ) { + + va_list argp; + va_start(argp, p_format); + vprintf(p_format, argp ); + va_end(argp); + +} +void OS_Unix::alert(const String& p_alert,const String& p_title) { + + fprintf(stderr,"ERROR: %s\n",p_alert.utf8().get_data()); +} + +static int has_data(FILE* p_fd, int timeout_usec = 0) { + + fd_set readset; + int fd = fileno(p_fd); + FD_ZERO(&readset); + FD_SET(fd, &readset); + timeval time; + time.tv_sec = 0; + time.tv_usec = timeout_usec; + int res = 0;//select(fd + 1, &readset, NULL, NULL, &time); + return res > 0; +}; + + +String OS_Unix::get_stdin_string(bool p_block) { + + String ret; + if (p_block) { + char buff[1024]; + ret = stdin_buf + fgets(buff,1024,stdin); + stdin_buf = ""; + return ret; + }; + + while (has_data(stdin)) { + + char ch; + read(fileno(stdin), &ch, 1); + if (ch == '\n') { + ret = stdin_buf; + stdin_buf = ""; + return ret; + } else { + char str[2] = { ch, 0 }; + stdin_buf += str; + }; + }; + + return ""; +} + +String OS_Unix::get_name() { + + return "Unix"; +} + + +uint64_t OS_Unix::get_unix_time() const { + + return time(NULL); +}; + + +OS::Date OS_Unix::get_date() const { + + time_t t=time(NULL); + struct tm *lt=localtime(&t); + Date ret; + ret.year=1900+lt->tm_year; + ret.month=(Month)lt->tm_mon; + ret.day=lt->tm_mday; + ret.weekday=(Weekday)lt->tm_wday; + ret.dst=lt->tm_isdst; + + return ret; +} +OS::Time OS_Unix::get_time() const { + + time_t t=time(NULL); + struct tm *lt=localtime(&t); + Time ret; + ret.hour=lt->tm_hour; + ret.min=lt->tm_min; + ret.sec=lt->tm_sec; + return ret; +} + +void OS_Unix::delay_usec(uint32_t p_usec) const { + + usleep(p_usec); +} +uint64_t OS_Unix::get_ticks_usec() const { + + struct timeval tv_now; + gettimeofday(&tv_now,NULL); + + uint64_t longtime = (uint64_t)tv_now.tv_usec + (uint64_t)tv_now.tv_sec*1000000L; + longtime-=ticks_start; + + return longtime; +} + +Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id,String* r_pipe,int *r_exitcode) { + + + if (p_blocking && r_pipe) { + + + String argss; + argss="\""+p_path+"\""; + + for(int i=0;i<p_arguments.size();i++) { + + argss+=String(" \"")+p_arguments[i]+"\""; + } + + argss+=" 2>/dev/null"; //silence stderr + FILE* f=popen(argss.utf8().get_data(),"r"); + + ERR_FAIL_COND_V(!f,ERR_CANT_OPEN); + + char buf[65535]; + while(fgets(buf,65535,f)) { + + (*r_pipe)+=buf; + } + + int rv = pclose(f); + if (r_exitcode) + *r_exitcode=rv; + + return OK; + } + + + pid_t pid = fork(); + ERR_FAIL_COND_V(pid<0,ERR_CANT_FORK); + //print("execute: %s\n",p_path.utf8().get_data()); + + + if (pid==0) { + // is child + Vector<CharString> cs; + cs.push_back(p_path.utf8()); + for(int i=0;i<p_arguments.size();i++) + cs.push_back(p_arguments[i].utf8()); + + Vector<char*> args; + for(int i=0;i<cs.size();i++) + args.push_back((char*)cs[i].get_data());// shitty C cast + args.push_back(0); + + execv(p_path.utf8().get_data(),&args[0]); + // still alive? something failed.. + fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data()); + abort(); + } + + if (p_blocking) { + + int status; + pid_t rpid = waitpid(pid,&status,0); + if (r_exitcode) + *r_exitcode=WEXITSTATUS(status); + + print("returned: %i, waiting for: %i\n",rpid,pid); + } else { + + if (r_child_id) + *r_child_id=pid; + } + + return OK; + +} + +Error OS_Unix::kill(const ProcessID& p_pid) { + + int ret = ::kill(p_pid,SIGKILL); + return ret?ERR_INVALID_PARAMETER:OK; +} + +bool OS_Unix::has_environment(const String& p_var) const { + + return getenv(p_var.utf8().get_data())!=NULL; +} + +String OS_Unix::get_locale() const { + + if (!has_environment("LANG")) + return "en"; + + String locale = get_environment("LANG"); + int tp = locale.find("."); + if (tp!=-1) + locale=locale.substr(0,tp); + return locale; +} + +Error OS_Unix::set_cwd(const String& p_cwd) { + + if (chdir(p_cwd.utf8().get_data())!=0) + return ERR_CANT_OPEN; + + return OK; +} + + +String OS_Unix::get_environment(const String& p_var) const { + + if (getenv(p_var.utf8().get_data())) + return getenv(p_var.utf8().get_data()); + return ""; +} + +int OS_Unix::get_processor_count() const { + + return sysconf(_SC_NPROCESSORS_CONF); +} + +String OS_Unix::get_data_dir() const { + + String an = Globals::get_singleton()->get("application/name"); + if (an!="") { + + if (has_environment("HOME")) { + + return get_environment("HOME")+"/."+an; + } + } + + return Globals::get_singleton()->get_resource_path(); + +} + +String OS_Unix::get_executable_path() const { + +#ifdef __linux__ + //fix for running from a symlink + char buf[256]; + memset(buf,0,256); + readlink("/proc/self/exe", buf, sizeof(buf)); + //print_line("Exec path is:"+String(buf)); + String b = buf; + if (b=="") { + WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]"); + return OS::get_executable_path(); + } + return b; +#else + ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly."); + return OS::get_executable_path(); +#endif +} + + +#endif diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h new file mode 100644 index 0000000000..72943ac25b --- /dev/null +++ b/drivers/unix/os_unix.h @@ -0,0 +1,121 @@ +/*************************************************************************/ +/* os_unix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef OS_UNIX_H +#define OS_UNIX_H + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + +#ifdef UNIX_ENABLED + + +#include "os/os.h" +#include "drivers/unix/ip_unix.h" + + +class OS_Unix : public OS { + + uint64_t ticks_start; +protected: + + // UNIX only handles the core functions. + // inheriting platforms under unix (eg. X11) should handle the rest + + //virtual int get_video_driver_count() const; + //virtual const char * get_video_driver_name(int p_driver) const; + //virtual VideoMode get_default_video_mode() const; + + virtual int get_audio_driver_count() const; + virtual const char * get_audio_driver_name(int p_driver) const; + + virtual void initialize_core(); + virtual int unix_initialize_audio(int p_audio_driver); + //virtual void initialize(int p_video_driver,int p_audio_driver); + + //virtual void finalize(); + virtual void finalize_core(); + + String stdin_buf; + +public: + + + virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR); + + virtual void print(const char *p_format, ... ); + virtual void vprint(const char* p_format, va_list p_list,bool p_stderr=false); + virtual void alert(const String& p_alert,const String& p_title="ALERT!"); + virtual String get_stdin_string(bool p_block); + + //virtual void set_mouse_show(bool p_show); + //virtual void set_mouse_grab(bool p_grab); + //virtual bool is_mouse_grab_enabled() const = 0; + //virtual void get_mouse_pos(int &x, int &y) const; + //virtual void set_window_title(const String& p_title); + + //virtual void set_video_mode(const VideoMode& p_video_mode); + //virtual VideoMode get_video_mode() const; + //virtual void get_fullscreen_mode_list(List<VideoMode> *p_list) const; + + virtual Error set_cwd(const String& p_cwd); + + virtual String get_name(); + + virtual Date get_date() const; + virtual Time get_time() const; + + virtual uint64_t get_unix_time() const; + + virtual void delay_usec(uint32_t p_usec) const; + virtual uint64_t get_ticks_usec() const; + + virtual Error execute(const String& p_path, const List<String>& p_arguments,bool p_blocking,ProcessID *r_child_id=NULL,String* r_pipe=NULL,int *r_exitcode=NULL); + virtual Error kill(const ProcessID& p_pid); + + virtual bool has_environment(const String& p_var) const; + virtual String get_environment(const String& p_var) const; + virtual String get_locale() const; + + virtual int get_processor_count() const; + + + virtual void debug_break(); + + virtual String get_executable_path() const; + virtual String get_data_dir() const; + + //virtual void run( MainLoop * p_main_loop ); + + +}; + +#endif + +#endif diff --git a/drivers/unix/semaphore_posix.cpp b/drivers/unix/semaphore_posix.cpp new file mode 100644 index 0000000000..6f1b8931f9 --- /dev/null +++ b/drivers/unix/semaphore_posix.cpp @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* semaphore_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "semaphore_posix.h" + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +#include "os/memory.h" +#include <errno.h> +#include <stdio.h> + +Error SemaphorePosix::wait() { + + + while(sem_wait(&sem)) { + if (errno==EINTR) { + errno=0; + continue; + } else { +perror("sem waiting"); + return ERR_BUSY; + } + } + return OK; +} + +Error SemaphorePosix::post() { + + return (sem_post(&sem)==0)?OK:ERR_BUSY; +} +int SemaphorePosix::get() const { + + int val; + sem_getvalue(&sem, &val); + + return val; +} + + +Semaphore *SemaphorePosix::create_semaphore_posix() { + + return memnew( SemaphorePosix ); +} + +void SemaphorePosix::make_default() { + + create_func=create_semaphore_posix; +} + +SemaphorePosix::SemaphorePosix() { + + int r = sem_init(&sem,0,0); + if (r != 0) + perror("sem creating"); +} + + +SemaphorePosix::~SemaphorePosix() { + + sem_destroy(&sem); +} + + +#endif diff --git a/drivers/unix/semaphore_posix.h b/drivers/unix/semaphore_posix.h new file mode 100644 index 0000000000..de563c28c4 --- /dev/null +++ b/drivers/unix/semaphore_posix.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* semaphore_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef SEMAPHORE_POSIX_H +#define SEMAPHORE_POSIX_H + + + +#include "os/semaphore.h" + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +#include <semaphore.h> +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ +class SemaphorePosix : public Semaphore { + + mutable sem_t sem; + + static Semaphore *create_semaphore_posix(); + +public: + + virtual Error wait(); + virtual Error post(); + virtual int get() const; + + static void make_default(); + SemaphorePosix(); + + ~SemaphorePosix(); + +}; + +#endif +#endif diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp new file mode 100644 index 0000000000..8d937d9ca8 --- /dev/null +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -0,0 +1,388 @@ +/*************************************************************************/ +/* stream_peer_tcp_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef UNIX_ENABLED + +#include "stream_peer_tcp_posix.h" + +#include <poll.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <netdb.h> +#include <sys/types.h> +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif +#include <netinet/in.h> + +#include <sys/socket.h> +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif + +#include <netinet/tcp.h> + +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) + #define MSG_NOSIGNAL SO_NOSIGPIPE +#endif + +static void set_addr_in(struct sockaddr_in& their_addr, const IP_Address& p_host, uint16_t p_port) { + + their_addr.sin_family = AF_INET; // host byte order + their_addr.sin_port = htons(p_port); // short, network byte order + their_addr.sin_addr = *((struct in_addr*)&p_host.host); + memset(&(their_addr.sin_zero), '\0', 8); +}; + +StreamPeerTCP* StreamPeerTCPPosix::_create() { + + return memnew(StreamPeerTCPPosix); +}; + +void StreamPeerTCPPosix::make_default() { + + StreamPeerTCP::_create = StreamPeerTCPPosix::_create; +}; + +Error StreamPeerTCPPosix::_block(int p_sockfd, bool p_read, bool p_write) const { + + struct pollfd pfd; + pfd.fd = p_sockfd; + pfd.events = 0; + if (p_read) + pfd.events |= POLLIN; + if (p_write) + pfd.events |= POLLOUT; + pfd.revents = 0; + + int ret = poll(&pfd, 1, -1); + return ret < 0 ? FAILED : OK; +}; + +Error StreamPeerTCPPosix::_poll_connection(bool p_block) const { + + ERR_FAIL_COND_V(status != STATUS_CONNECTING || sockfd == -1, FAILED); + + if (p_block) { + + _block(sockfd, false, true); + }; + + struct sockaddr_in their_addr; + set_addr_in(their_addr, peer_host, peer_port); + if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) { + + if (errno == EISCONN) { + status = STATUS_CONNECTED; + return OK; + }; + + return OK; + } else { + + status = STATUS_CONNECTED; + return OK; + }; + + return OK; +}; + +void StreamPeerTCPPosix::set_socket(int p_sockfd, IP_Address p_host, int p_port) { + + sockfd = p_sockfd; +#ifndef NO_FCNTL + fcntl(sockfd, F_SETFL, O_NONBLOCK); +#else + int bval = 1; + ioctl(sockfd, FIONBIO, &bval); + +#endif + status = STATUS_CONNECTING; + + peer_host = p_host; + peer_port = p_port; +}; + +Error StreamPeerTCPPosix::connect(const IP_Address& p_host, uint16_t p_port) { + + ERR_FAIL_COND_V( p_host.host == 0, ERR_INVALID_PARAMETER); + + if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { + ERR_PRINT("Socket creation failed!"); + disconnect(); + //perror("socket"); + return FAILED; + }; + +#ifndef NO_FCNTL + fcntl(sockfd, F_SETFL, O_NONBLOCK); +#else + int bval = 1; + ioctl(sockfd, FIONBIO, &bval); +#endif + + struct sockaddr_in their_addr; + set_addr_in(their_addr, p_host, p_port); + + errno = 0; + if (::connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1 && errno != EINPROGRESS) { + + ERR_PRINT("Connection to remote host failed!"); + disconnect(); + return FAILED; + }; + + if (errno == EINPROGRESS) { + status = STATUS_CONNECTING; + } else { + status = STATUS_CONNECTED; + }; + + peer_host = p_host; + peer_port = p_port; + + return OK; +}; + +Error StreamPeerTCPPosix::write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block) { + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + + if (_poll_connection(p_block) != OK) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + r_sent = 0; + return OK; + }; + }; + + int data_to_send = p_bytes; + const uint8_t *offset = p_data; + if (sockfd == -1) return FAILED; + errno = 0; + int total_sent = 0; + + while (data_to_send) { + + int sent_amount = send(sockfd, offset, data_to_send, MSG_NOSIGNAL); + //printf("Sent TCP data of %d bytes, errno %d\n", sent_amount, errno); + + if (sent_amount == -1) { + + if (errno != EAGAIN) { + + perror("shit?"); + disconnect(); + ERR_PRINT("Server disconnected!\n"); + return FAILED; + }; + + if (!p_block) { + r_sent = total_sent; + return OK; + }; + + _block(sockfd, false, true); + } else { + + data_to_send -= sent_amount; + offset += sent_amount; + total_sent += sent_amount; + }; + } + + r_sent = total_sent; + + return OK; +}; + +Error StreamPeerTCPPosix::read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block) { + + if (!is_connected()) { + + return FAILED; + }; + + if (status == STATUS_CONNECTING) { + + if (_poll_connection(p_block) != OK) { + + return FAILED; + }; + + if (status != STATUS_CONNECTED) { + r_received = 0; + return OK; + }; + }; + + int to_read = p_bytes; + int total_read = 0; + errno = 0; + + while (to_read) { + + int read = recv(sockfd, p_buffer + total_read, to_read, 0); + + if (read == -1) { + + if (errno != EAGAIN) { + + perror("shit?"); + disconnect(); + ERR_PRINT("Server disconnected!\n"); + return FAILED; + }; + + if (!p_block) { + + r_received = total_read; + return OK; + }; + _block(sockfd, true, false); + + } else if (read==0) { + + sockfd=-1; + status = STATUS_NONE; + peer_port = 0; + peer_host = IP_Address(); + return ERR_FILE_EOF; + + } else { + + to_read -= read; + total_read += read; + }; + }; + + r_received = total_read; + + return OK; +}; + +void StreamPeerTCPPosix::set_nodelay(bool p_enabled) { + + ERR_FAIL_COND(!is_connected()); + int flag=p_enabled?1:0; + setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int)); +} + +bool StreamPeerTCPPosix::is_connected() const { + + if (status == STATUS_NONE || status == STATUS_ERROR) { + + return false; + }; + if (status != STATUS_CONNECTED) { + return true; + }; + + return (sockfd!=-1); +}; + +StreamPeerTCP::Status StreamPeerTCPPosix::get_status() const { + + if (status == STATUS_CONNECTING) { + _poll_connection(false); + }; + + return status; +}; + + +void StreamPeerTCPPosix::disconnect() { + + if (sockfd != -1) + close(sockfd); + sockfd=-1; + + status = STATUS_NONE; + peer_port = 0; + peer_host = IP_Address(); +}; + + +Error StreamPeerTCPPosix::put_data(const uint8_t* p_data,int p_bytes) { + + int total; + return write(p_data, p_bytes, total, true); +}; + +Error StreamPeerTCPPosix::put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent) { + + return write(p_data, p_bytes, r_sent, false); +}; + +Error StreamPeerTCPPosix::get_data(uint8_t* p_buffer, int p_bytes) { + + int total; + return read(p_buffer, p_bytes, total, true); +}; + +Error StreamPeerTCPPosix::get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received) { + + return read(p_buffer, p_bytes, r_received, false); +}; + +IP_Address StreamPeerTCPPosix::get_connected_host() const { + + return peer_host; +}; + +uint16_t StreamPeerTCPPosix::get_connected_port() const { + + return peer_port; +}; + +StreamPeerTCPPosix::StreamPeerTCPPosix() { + + sockfd = -1; + status = STATUS_NONE; + peer_port = 0; +}; + +StreamPeerTCPPosix::~StreamPeerTCPPosix() { + + disconnect(); +}; + +#endif diff --git a/drivers/unix/stream_peer_tcp_posix.h b/drivers/unix/stream_peer_tcp_posix.h new file mode 100644 index 0000000000..1259b46ff2 --- /dev/null +++ b/drivers/unix/stream_peer_tcp_posix.h @@ -0,0 +1,89 @@ +/*************************************************************************/ +/* stream_peer_tcp_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef UNIX_ENABLED + +#ifndef STREAM_PEER_TCP_POSIX_H +#define STREAM_PEER_TCP_POSIX_H + +#include "core/io/ip_address.h" +#include "core/io/stream_peer_tcp.h" +#include "error_list.h" + +#include "core/io/ip_address.h" + +class StreamPeerTCPPosix : public StreamPeerTCP { + +protected: + + mutable Status status; + + int sockfd; + + Error _block(int p_sockfd, bool p_read, bool p_write) const; + + Error _poll_connection(bool p_block) const; + + IP_Address peer_host; + int peer_port; + + Error write(const uint8_t* p_data,int p_bytes, int &r_sent, bool p_block); + Error read(uint8_t* p_buffer, int p_bytes,int &r_received, bool p_block); + + static StreamPeerTCP* _create(); + +public: + + virtual Error connect(const IP_Address& p_host, uint16_t p_port); + + virtual Error put_data(const uint8_t* p_data,int p_bytes); + virtual Error put_partial_data(const uint8_t* p_data,int p_bytes, int &r_sent); + + virtual Error get_data(uint8_t* p_buffer, int p_bytes); + virtual Error get_partial_data(uint8_t* p_buffer, int p_bytes,int &r_received); + + void set_socket(int p_sockfd, IP_Address p_host, int p_port); + + virtual IP_Address get_connected_host() const; + virtual uint16_t get_connected_port() const; + + virtual bool is_connected() const; + virtual Status get_status() const; + virtual void disconnect(); + + virtual void set_nodelay(bool p_enabled); + + static void make_default(); + + StreamPeerTCPPosix(); + ~StreamPeerTCPPosix(); +}; + +#endif // TCP_CLIENT_POSIX_H + +#endif diff --git a/drivers/unix/tcp_server_posix.cpp b/drivers/unix/tcp_server_posix.cpp new file mode 100644 index 0000000000..f91ad36ef9 --- /dev/null +++ b/drivers/unix/tcp_server_posix.cpp @@ -0,0 +1,178 @@ +/*************************************************************************/ +/* tcp_server_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "tcp_server_posix.h" +#include "stream_peer_tcp_posix.h" + +#ifdef UNIX_ENABLED + +#include <poll.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <netdb.h> +#include <sys/types.h> +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif +#include <netinet/in.h> +#include <sys/socket.h> +#include <assert.h> +TCP_Server* TCPServerPosix::_create() { + + return memnew(TCPServerPosix); +}; + +void TCPServerPosix::make_default() { + + TCP_Server::_create = TCPServerPosix::_create; +}; + +Error TCPServerPosix::listen(uint16_t p_port,const List<String> *p_accepted_hosts) { + + printf("********* listening on port %i\n", p_port); + int sockfd; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + ERR_FAIL_COND_V(sockfd == -1, FAILED); +#ifndef NO_FCNTL + fcntl(sockfd, F_SETFL, O_NONBLOCK); +#else + int bval = 1; + ioctl(sockfd, FIONBIO, &bval); +#endif + + int reuse=1; + if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0) { + + printf("REUSEADDR failed!"); + } + + struct sockaddr_in my_addr; + my_addr.sin_family = AF_INET; // host byte order + my_addr.sin_port = htons(p_port); // short, network byte order + my_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP TODO: use p_accepted_hosts + memset(my_addr.sin_zero, '\0', sizeof my_addr.sin_zero); + + if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof my_addr) != -1) { + + if (::listen(sockfd, 1) == -1) { + + close(sockfd); + ERR_FAIL_V(FAILED); + }; + }; + + if (listen_sockfd != -1) { + + printf("FAILED\n"); + stop(); + }; + + listen_sockfd = sockfd; + + printf("OK! %i\n", listen_sockfd); + return OK; +}; + +bool TCPServerPosix::is_connection_available() const { + + if (listen_sockfd == -1) { + return false; + }; + + struct pollfd pfd; + pfd.fd = listen_sockfd; + pfd.events = POLLIN; + pfd.revents = 0; + + int ret = poll(&pfd, 1, 0); + ERR_FAIL_COND_V(ret < 0, FAILED); + + if (ret && (pfd.revents & POLLIN)) { + printf("has connection!\n"); + return true; + }; + + return false; +}; + +Ref<StreamPeerTCP> TCPServerPosix::take_connection() { + + if (!is_connection_available()) { + return Ref<StreamPeerTCP>(); + }; + + struct sockaddr_in their_addr; + socklen_t sin_size = sizeof(their_addr); + int fd = accept(listen_sockfd, (struct sockaddr *)&their_addr, &sin_size); + ERR_FAIL_COND_V(fd == -1, Ref<StreamPeerTCP>()); +#ifndef NO_FCNTL + fcntl(fd, F_SETFL, O_NONBLOCK); +#else + int bval = 1; + ioctl(fd, FIONBIO, &bval); +#endif + + Ref<StreamPeerTCPPosix> conn = memnew(StreamPeerTCPPosix); + IP_Address ip; + ip.host = (uint32_t)their_addr.sin_addr.s_addr; + conn->set_socket(fd, ip, ntohs(their_addr.sin_port)); + + return conn; +}; + +void TCPServerPosix::stop() { + + if (listen_sockfd != -1) { + print_line("CLOSING CONNECTION"); + int ret = close(listen_sockfd); + ERR_FAIL_COND(ret!=0); + }; + + listen_sockfd = -1; +}; + + +TCPServerPosix::TCPServerPosix() { + + listen_sockfd = -1; +}; + +TCPServerPosix::~TCPServerPosix() { + + stop(); +}; +#endif diff --git a/drivers/unix/tcp_server_posix.h b/drivers/unix/tcp_server_posix.h new file mode 100644 index 0000000000..053aba0d10 --- /dev/null +++ b/drivers/unix/tcp_server_posix.h @@ -0,0 +1,57 @@ +/*************************************************************************/ +/* tcp_server_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef TCP_SERVER_POSIX_H +#define TCP_SERVER_POSIX_H + +#ifdef UNIX_ENABLED +#include "core/io/tcp_server.h" + +class TCPServerPosix : public TCP_Server { + + int listen_sockfd; + + static TCP_Server* _create(); + +public: + + virtual Error listen(uint16_t p_port,const List<String> *p_accepted_hosts=NULL); + virtual bool is_connection_available() const; + virtual Ref<StreamPeerTCP> take_connection(); + + virtual void stop(); + + static void make_default(); + + TCPServerPosix(); + ~TCPServerPosix(); +}; + + +#endif // TCP_SERVER_POSIX_H +#endif diff --git a/drivers/unix/thread_posix.cpp b/drivers/unix/thread_posix.cpp new file mode 100644 index 0000000000..b2f1e144bb --- /dev/null +++ b/drivers/unix/thread_posix.cpp @@ -0,0 +1,99 @@ +/*************************************************************************/ +/* thread_posix.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#include "thread_posix.h" + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +#include "os/memory.h" + +Thread::ID ThreadPosix::get_ID() const { + + return id; +} + +Thread* ThreadPosix::create_thread_posix() { + + return memnew( ThreadPosix ); +} + +void *ThreadPosix::thread_callback(void *userdata) { + + ThreadPosix *t=reinterpret_cast<ThreadPosix*>(userdata); + t->callback(t->user); + t->id=(ID)pthread_self(); + return NULL; +} + +Thread* ThreadPosix::create_func_posix(ThreadCreateCallback p_callback,void *p_user,const Settings&) { + + ThreadPosix *tr= memnew(ThreadPosix); + tr->callback=p_callback; + tr->user=p_user; + pthread_attr_init(&tr->pthread_attr); + pthread_attr_setdetachstate(&tr->pthread_attr, PTHREAD_CREATE_JOINABLE); + + pthread_create(&tr->pthread, &tr->pthread_attr, thread_callback, tr); + + return tr; +} +Thread::ID ThreadPosix::get_thread_ID_func_posix() { + + return (ID)pthread_self(); +} +void ThreadPosix::wait_to_finish_func_posix(Thread* p_thread) { + + ThreadPosix *tp=static_cast<ThreadPosix*>(p_thread); + ERR_FAIL_COND(!tp); + ERR_FAIL_COND(tp->pthread==0); + + pthread_join(tp->pthread,NULL); + tp->pthread=0; +} + + +void ThreadPosix::make_default() { + + create_func=create_func_posix; + get_thread_ID_func=get_thread_ID_func_posix; + wait_to_finish_func=wait_to_finish_func_posix; + +} + +ThreadPosix::ThreadPosix() { + + pthread=0; +} + + +ThreadPosix::~ThreadPosix() { + +} + + +#endif diff --git a/drivers/unix/thread_posix.h b/drivers/unix/thread_posix.h new file mode 100644 index 0000000000..a088f1d5de --- /dev/null +++ b/drivers/unix/thread_posix.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* thread_posix.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifndef THREAD_POSIX_H +#define THREAD_POSIX_H + +/** + @author Juan Linietsky <reduzio@gmail.com> +*/ + +#if defined(UNIX_ENABLED) || defined(PTHREAD_ENABLED) + +#include <sys/types.h> +#include <pthread.h> +#include "os/thread.h" + +class ThreadPosix : public Thread { + + pthread_t pthread; + pthread_attr_t pthread_attr; + ThreadCreateCallback callback; + void *user; + ID id; + + static Thread* create_thread_posix(); + + + static void *thread_callback(void *userdata); + + static Thread* create_func_posix(ThreadCreateCallback p_callback,void *,const Settings&); + static ID get_thread_ID_func_posix(); + static void wait_to_finish_func_posix(Thread* p_thread); + + ThreadPosix(); +public: + + + virtual ID get_ID() const; + + static void make_default(); + + + ~ThreadPosix(); + +}; + + +#endif + +#endif |