OSDN Git Service

2001-02-15 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / libsupc++ / vec.cc
1 // New abi Support -*- C++ -*-
2
3 // Copyright (C) 2000, 2001 Free Software Foundation, Inc.
4 //  
5 // This file is part of GNU CC.
6 //
7 // GNU CC is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2, or (at your option)
10 // any later version.
11
12 // GNU CC is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16
17 // You should have received a copy of the GNU General Public License
18 // along with GNU CC; see the file COPYING.  If not, write to
19 // the Free Software Foundation, 59 Temple Place - Suite 330,
20 // Boston, MA 02111-1307, USA. 
21
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction.  Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License.  This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
30
31 // Written by Nathan Sidwell, Codesourcery LLC, <nathan@codesourcery.com>
32
33 #include <cxxabi.h>
34 #include <new>
35 #include <exception>
36 #include <exception_defines.h>
37
38 #include "exception_support.h"
39
40 namespace __cxxabiv1
41 {
42   namespace 
43   {
44     struct uncatch_exception 
45     {
46       uncatch_exception () { p = __uncatch_exception (); }
47       ~uncatch_exception () { __recatch_exception (p); }
48       
49       cp_eh_info *p;
50     };
51   }
52
53   // Allocate and construct array.
54   extern "C" void *
55   __cxa_vec_new(std::size_t element_count,
56                 std::size_t element_size,
57                 std::size_t padding_size,
58                 void (*constructor) (void *),
59                 void (*destructor) (void *))
60   {
61     return __cxa_vec_new2(element_count, element_size, padding_size,
62                            constructor, destructor,
63                            &operator new[], &operator delete []);
64   }
65
66   extern "C" void *
67   __cxa_vec_new2(std::size_t element_count,
68                  std::size_t element_size,
69                  std::size_t padding_size,
70                  void (*constructor) (void *),
71                  void (*destructor) (void *),
72                  void *(*alloc) (size_t),
73                  void (*dealloc) (void *))
74   {
75     std::size_t size = element_count * element_size + padding_size;
76     char *base = static_cast <char *> (alloc (size));
77     
78     if (padding_size)
79       {
80         base += padding_size;
81         reinterpret_cast <std::size_t *> (base)[-1] = element_count;
82       }
83     try
84       {
85         __cxa_vec_ctor(base, element_count, element_size,
86                        constructor, destructor);
87       }
88     catch (...)
89       {
90         {
91           uncatch_exception ue;
92           dealloc(base - padding_size);
93         }
94         __throw_exception_again;
95       }
96     return base;
97   }
98   
99   extern "C" void *
100   __cxa_vec_new3(std::size_t element_count,
101                  std::size_t element_size,
102                  std::size_t padding_size,
103                  void (*constructor) (void *),
104                  void (*destructor) (void *),
105                  void *(*alloc) (std::size_t),
106                  void (*dealloc) (void *, std::size_t))
107   {
108     std::size_t size = element_count * element_size + padding_size;
109     char *base = static_cast<char *>(alloc (size));
110     
111     if (padding_size)
112       {
113         base += padding_size;
114         reinterpret_cast<std::size_t *>(base)[-1] = element_count;
115       }
116     try
117       {
118         __cxa_vec_ctor(base, element_count, element_size,
119                        constructor, destructor);
120       }
121     catch (...)
122       {
123         {
124           uncatch_exception ue;
125           dealloc(base - padding_size, size);
126         }
127         __throw_exception_again;
128       }
129     return base;
130   }
131   
132   // Construct array.
133   extern "C" void
134   __cxa_vec_ctor(void *array_address,
135                  std::size_t element_count,
136                  std::size_t element_size,
137                  void (*constructor) (void *),
138                  void (*destructor) (void *))
139   {
140     std::size_t ix = 0;
141     char *ptr = static_cast<char *>(array_address);
142     
143     try
144       {
145         if (constructor)
146           for (; ix != element_count; ix++, ptr += element_size)
147             constructor(ptr);
148       }
149     catch (...)
150       {
151         {
152           uncatch_exception ue;
153           __cxa_vec_dtor(array_address, ix, element_size, destructor);
154         }
155         __throw_exception_again;
156       }
157   }
158   
159   // Construct an array by copying.
160   extern "C" void
161   __cxa_vec_cctor(void *dest_array,
162                   void *src_array,
163                   std::size_t element_count,
164                   std::size_t element_size,
165                   void (*constructor) (void *, void *),
166                   void (*destructor) (void *))
167   {
168     std::size_t ix = 0;
169     char *dest_ptr = static_cast<char *>(dest_array);
170     char *src_ptr = static_cast<char *>(src_array);
171     
172     try
173       {
174         if (constructor)
175           for (; ix != element_count; 
176                ix++, src_ptr += element_size, dest_ptr += element_size)
177             constructor(dest_ptr, src_ptr);
178       }
179     catch (...)
180       {
181         {
182           uncatch_exception ue;
183           __cxa_vec_dtor (dest_array, ix, element_size, destructor);
184         }
185         __throw_exception_again;
186       }
187   }
188   
189   // Destruct array.
190   extern "C" void
191   __cxa_vec_dtor(void *array_address,
192                  std::size_t element_count,
193                  std::size_t element_size,
194                  void (*destructor) (void *))
195   {
196     if (destructor)
197       {
198         char *ptr = static_cast<char *>(array_address);
199         std::size_t ix = element_count;
200         bool unwinding = std::uncaught_exception();
201       
202         ptr += element_count * element_size;
203       
204         try
205           {
206             while (ix--)
207               {
208                 ptr -= element_size;
209                 destructor(ptr);
210               }
211           }
212         catch (...)
213           {
214             if (unwinding)
215               // [except.ctor]/3 If a destructor called during stack unwinding
216               // exits with an exception, terminate is called.
217               std::terminate ();
218             {
219               uncatch_exception ue;
220               __cxa_vec_dtor(array_address, ix, element_size, destructor);
221             }
222             __throw_exception_again;
223           }
224       }
225   }
226
227   // Destruct and release array.
228   extern "C" void
229   __cxa_vec_delete(void *array_address,
230                    std::size_t element_size,
231                    std::size_t padding_size,
232                    void (*destructor) (void *))
233   {
234     __cxa_vec_delete2(array_address, element_size, padding_size,
235                        destructor,
236                        &operator delete []);
237   }
238
239   extern "C" void
240   __cxa_vec_delete2(void *array_address,
241                     std::size_t element_size,
242                     std::size_t padding_size,
243                     void (*destructor) (void *),
244                     void (*dealloc) (void *))
245   {
246     char *base = static_cast<char *>(array_address);
247   
248     if (padding_size)
249       {
250         std::size_t element_count = reinterpret_cast<std::size_t *>(base)[-1];
251         base -= padding_size;
252         try
253           {
254             __cxa_vec_dtor(array_address, element_count, element_size,
255                            destructor);
256           }
257         catch (...)
258           {
259             {
260               uncatch_exception ue;
261               dealloc(base);
262             }
263             __throw_exception_again;
264           }
265       }
266     dealloc(base);
267   }
268
269   extern "C" void
270   __cxa_vec_delete3(void *array_address,
271                     std::size_t element_size,
272                     std::size_t padding_size,
273                      void (*destructor) (void *),
274                     void (*dealloc) (void *, std::size_t))
275   {
276     char *base = static_cast <char *> (array_address);
277     std::size_t size = 0;
278     
279     if (padding_size)
280       {
281         std::size_t element_count = reinterpret_cast<std::size_t *> (base)[-1];
282         base -= padding_size;
283         size = element_count * element_size + padding_size;
284         try
285           {
286             __cxa_vec_dtor(array_address, element_count, element_size,
287                            destructor);
288           }
289         catch (...)
290           {
291             {
292               uncatch_exception ue;
293               dealloc(base, size);
294             }
295             __throw_exception_again;
296           }
297       }
298     dealloc(base, size);
299   }
300 } // namespace __cxxabiv1