1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 
13 #include <cstring>
14 
15 #include "chrono/core/ChGlobal.h"
16 
17 #include "chrono_thirdparty/filesystem/path.h"
18 
19 #if defined(_WIN32) || defined(_WIN64)
20 #include "Windows.h"
21 #endif
22 
23 #if defined(__APPLE__)
24 #include <libkern/OSAtomic.h>
25 #endif
26 
27 namespace chrono {
28 
29 // -----------------------------------------------------------------------------
30 // Functions for assigning unique identifiers
31 // -----------------------------------------------------------------------------
32 
33 // Set the start value for the sequence of IDs (ATTENTION: not thread safe)
34 // Subsequent calls to GetUniqueIntID() will return val+1, val+2, etc.
35 static volatile int first_id = 100000;
36 
SetFirstIntID(int val)37 void SetFirstIntID(int val) {
38     first_id = val;
39 }
40 
41 // Obtain a unique identifier (thread-safe; platform-dependent)
42 #if (defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) || defined(__EMSCRIPTEN__))
43 
GetUniqueIntID()44 int GetUniqueIntID() {
45     static volatile int id = first_id;
46     return __sync_add_and_fetch(&id, 1);
47 }
48 
49 #elif defined(_WIN32)
50 
GetUniqueIntID()51 int GetUniqueIntID() {
52     volatile static long id = first_id;
53     return (int)InterlockedIncrement(&id);
54 }
55 
56 #elif defined(_WIN64)
57 
GetUniqueIntID()58 int GetUniqueIntID() {
59     volatile static long long id = first_id;
60     return (int)InterlockedIncrement64(&id);
61 }
62 
63 #elif defined(__APPLE__)
64 
GetUniqueIntID()65 int GetUniqueIntID() {
66     static volatile int32_t id = first_id;
67     return (int)OSAtomicIncrement32Barrier(&id);
68 }
69 
70 #else
71 
72 //// TODO
73 #error "No support for atomic operations on current platform!"
74 
75 #endif
76 
77 // -----------------------------------------------------------------------------
78 // Functions for manipulating the Chrono data directory
79 // -----------------------------------------------------------------------------
80 
81 static std::string chrono_data_path("../data/");
82 
83 // Set the path to the Chrono data directory (ATTENTION: not thread safe)
SetChronoDataPath(const std::string & path)84 void SetChronoDataPath(const std::string& path) {
85     chrono_data_path = path;
86 }
87 
88 // Obtain the current path to the Chrono data directory (thread safe)
GetChronoDataPath()89 const std::string& GetChronoDataPath() {
90     return chrono_data_path;
91 }
92 
93 // Obtain the complete path to the specified filename, given relative to the
94 // Chrono data directory (thread safe)
GetChronoDataFile(const std::string & filename)95 std::string GetChronoDataFile(const std::string& filename) {
96     return chrono_data_path + filename;
97 }
98 
99 // -----------------------------------------------------------------------------
100 // Functions for manipulating the Chrono data directory
101 // -----------------------------------------------------------------------------
102 
103 static std::string chrono_out_path("DEMO_OUTPUT/");
104 
105 // Set the path to the Chrono output directory (ATTENTION: not thread safe)
SetChronoOutputPath(const std::string & path)106 void SetChronoOutputPath(const std::string& path) {
107     chrono_out_path = path;
108 }
109 
GetChronoOutputPath()110 const std::string& GetChronoOutputPath() {
111     // If the directory does not yet exists, create it.
112     auto out_path = filesystem::path(chrono_out_path);
113     if (!out_path.exists())
114         filesystem::create_directory(out_path);
115 
116     return chrono_out_path;
117 }
118 
119 }  // end namespace chrono
120