473,414 Members | 1,764 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

[allocator.concept] smart pointer clarifications

I am currently writting a smart pointer which is reasonnably stable and I
decided supporting allocators for completion because of its increase in
efficiency when the same pool used by containers is shared. I was told the
new standards are being finalized and I am hoping minor but important
changes could be applied before anything else.

To give a quick overview on the current status of this topic, you will find
below the latest text relating to allocator member functions (n2641). We
see over there there are no dictinction between the pointer type returned by
allocate() and the pointer type expected by deallocate() and destroy().
This is a big problem because this logic doesn't make sense anymore if smart
pointers are to be used. Smart pointers are owners of their objects and
aren't in no way going to give away external access to its object. We need
these functions to use
1) distinct pointer type from the one returned by allocate()
2) make the parameter (pointer) passed as a non-const reference

The latter is necessary to make changes to either the smart pointer itself
or the object pointed to in case raw pointer are used. We can see my
personnal implementation here and I would like to propose the following
function signatures:

template <typename T>
class shifted_allocator
{
public:
typedef shifted<T value_type;
typedef shifted_ptr<T pointer;
typedef shifted_ptr<const T const_pointer;

value_type * allocate(size_type s, const void * = 0);
void deallocate(pointer & p, size_type);
void construct(value_type * p, const T & x);
void destroy(pointer & p);
...
};

** Allocator member functions **
1)
pointer X::allocate(size_type n);
pointer X::allocate(size_type n, const_generic_pointer hint);

Effects: Memory is allocated for n objects of type value_type but the
objects are not constructed. [Footnote: It is intended that a.allocate be an
efficient means of allocating a single object of type T, even when sizeof(T)
is small. That is, there is no need for a container to maintain its own
"free list". - end footnote] The optional argument, p, may

Returns: A pointer to the allocated memory. [Note: If n == 0, the return
value is unspecified. If n 1, the means by which a program gains access to
the second and subsequent allocated objects is determined outside of the
Allocator concept. See RandomAccessAllocator, below, for one common
approach. - end note]

Throws: allocate may raise an appropriate exception.

Remark: The use of hint is unspecified, but intended as an aid to locality
if an implementation so desires. [ Note: In a container member function, the
address of an adjacent element is often a good choice to pass for the hint
argument. - end note ]

2)
void X::deallocate(pointer p, size_type n);

Preconditions: All n value_type objects in the area pointed to by p shall be
destroyed prior to this call. n shall match the value passed to allocate to
obtain this memory. [Note: p shall not be singular. - end note]

Throws: Does not throw exceptions.

3)
void X::destroy(pointer p);

Effects: Calls the destructor on the object at p but does not deallocate it.

Regards,
-Phil

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Aug 18 '08 #1
13 2034
On Aug 18, 7:28*pm, "Phil Bouchard" <p...@fornux.comwrote:
I am currently writting a smart pointer which is reasonnably stable and I
decided supporting allocators for completion because of its increase in
efficiency when the same pool used by containers is shared. *I was toldthe
new standards are being finalized and I am hoping minor but important
changes could be applied before anything else.

To give a quick overview on the current status of this topic, you will find
below the latest text relating to allocator member functions (n2641). *We
see over there there are no dictinction between the pointer type returnedby
allocate() and the pointer type expected by deallocate() and destroy().
This is a big problem because this logic doesn't make sense anymore if smart
pointers are to be used. *Smart pointers are owners of their objects and
aren't in no way going to give away external access to its object. *We need
these functions to use
1) distinct pointer type from the one returned by allocate()
2) make the parameter (pointer) passed as a non-const reference

The latter is necessary to make changes to either the smart pointer itself
or the object pointed to in case raw pointer are used. *We can see my
personnal implementation here and I would like to propose the following
function signatures:

template <typename T>
* * class shifted_allocator
* * {
* * public:
* * * * typedef shifted<T* * * * * * *value_type;
* * * * typedef shifted_ptr<T* * * * *pointer;
* * * * typedef shifted_ptr<const T* *const_pointer;

* * * * value_type * allocate(size_type s, const void * = 0);
* * * * void deallocate(pointer & p, size_type);
* * * * void construct(value_type * p, const T & x);
* * * * void destroy(pointer & p);
* * * * ...
* * };
[snip]

Perhaps I'm missing something. Smart pointers generally take over
ownership AFTER allocation, e.g.:

tr1::shared_ptr<intspi1( new int(42) );
tr1::shared_ptr<intspi2( FactoryFunction() );

A shared_ptr's deleter can tell it how to do some special release
procedure, e.g.:

tr1::shared_ptr<FILEfile( fopen( "some.txt", "r" ), &fclose );

Why do allocators need to become aware of smart pointers?

Cheers! --M
Aug 19 '08 #2

"mlimber" <ml*****@gmail.comwrote in message
news:e8**********************************@x35g2000 hsb.googlegroups.com...

[...]
Perhaps I'm missing something. Smart pointers generally take over
ownership AFTER allocation, e.g.:

tr1::shared_ptr<intspi1( new int(42) );
tr1::shared_ptr<intspi2( FactoryFunction() );

A shared_ptr's deleter can tell it how to do some special release
procedure, e.g.:

tr1::shared_ptr<FILEfile( fopen( "some.txt", "r" ), &fclose );

Why do allocators need to become aware of smart pointers?

Cheers! --M
Well the idea of having of defining an allocator is to centralized in one
class instanciation everything related to memory management. If the
allocator have to be explicitly shared between the container and the smart
pointer itself then the idea becomes pointless. The allocator should be
responsible for all types of deallocations, including smart pointers.
-Phil
Aug 20 '08 #3
On Aug 20, 4:26*am, "Phil Bouchard" <p...@fornux.comwrote:
"mlimber" <mlim...@gmail.comwrote in message

news:e8**********************************@x35g2000 hsb.googlegroups.com...

[...]
Perhaps I'm missing something. Smart pointers generally take over
ownership AFTER allocation, e.g.:
*tr1::shared_ptr<intspi1( new int(42) );
*tr1::shared_ptr<intspi2( FactoryFunction() );
A shared_ptr's deleter can tell it how to do some special release
procedure, e.g.:
*tr1::shared_ptr<FILEfile( fopen( "some.txt", "r" ), &fclose );
Why do allocators need to become aware of smart pointers?

Well the idea of having of defining an allocator is to centralized in one
class instanciation everything related to memory management. *If the
allocator have to be explicitly shared between the container and the smart
pointer itself then the idea becomes pointless. *The allocator should be
responsible for all types of deallocations, including smart pointers.
I still don't get it. Let's say you're designing std::vector, which
has an allocator template parameter. It doesn't matter if the user-
defined class or a smart pointer (as long as it has value semantics).
Given this code:

class C { */...*/ };
// ...
std::vector<Cv1( 10 );
std::vector< std::tr1::shared_ptr<C v2( 10 );

Under the hood, each of the latter two lines will use vector's
(default) allocator to grab memory for the 10 instances of the
contained type and then placement-new to construct the instances in
that memory. (Note that all the shared_ptr's pointees are null at this
point.) Why does the allocator care if it's making a C or a
shared_ptr<C>?

Cheers! --M
Aug 20 '08 #4
"mlimber" <ml*****@gmail.comwrote in message
news:b5**********************************@e53g2000 hsa.googlegroups.com...
On Aug 20, 4:26 am, "Phil Bouchard" <p...@fornux.comwrote:

[...]
I still don't get it. Let's say you're designing std::vector, which
has an allocator template parameter. It doesn't matter if the user-
defined class or a smart pointer (as long as it has value semantics).
Given this code:

class C { */...*/ };
// ...
std::vector<Cv1( 10 );
std::vector< std::tr1::shared_ptr<C v2( 10 );

Under the hood, each of the latter two lines will use vector's
(default) allocator to grab memory for the 10 instances of the
contained type and then placement-new to construct the instances in
that memory. (Note that all the shared_ptr's pointees are null at this
point.) Why does the allocator care if it's making a C or a
shared_ptr<C>?

Cheers! --M
Indeed in that case it won't matter because the pools used to allocate nodes
from the container and to deallocate objects from the smart pointer are not
shared. Sometimes it is in our favor to share to same pool used by the
container and the smart pointer. For example shifted_ptr<uses this to
prevent cyclicism (still requires STL modifications).

Either we do it this way or we share the allocator across the container and
smart pointer so that the smart pointer uses deallocate(void *):

1)
std::vector<shifted_ptr<int>, shifted_allocator<shifted_ptr<int c1;

2)
std::vector<shifted_ptr<int, shifted_allocator<int,
shifted_allocator<shifted_ptr<int, shifted_allocator<int c2;

I don't even think option 2) is implementable.
-Phil
Aug 20 '08 #5

"Phil Bouchard" <ph**@fornux.comwrote in message
news:g8**********@aioe.org...

[...]
The latter is necessary to make changes to either the smart pointer itself
or the object pointed to in case raw pointer are used. We can see my
personnal implementation here and I would like to propose the following
function signatures:

template <typename T>
class shifted_allocator
{
public:
typedef shifted<T value_type;
typedef shifted_ptr<T pointer;
typedef shifted_ptr<const T const_pointer;

value_type * allocate(size_type s, const void * = 0);
void deallocate(pointer & p, size_type);
void construct(value_type * p, const T & x);
void destroy(pointer & p);
...
};
[...]

Moreover it turns out this will become an even bigger problem if the new
rule of virtualizing allocator is accepted because the parameters will be
totaly different:

namespace std
{
class allocator_implementation
{
typedef void * pointer;

virtual void deallocate(pointer p, size_type) = 0;
...
};
}

template <typename T>
class shifted_allocator : std::allocator_implementation
{
public:
typedef shifted<T value_type;
typedef shifted_ptr<T pointer;
typedef shifted_ptr<const T const_pointer;

virtual void deallocate(pointer & p, size_type) // won't override
{
}
...
};

I think the idea of virtualizing the allocators should not be accepted
because it will be irreversible. Correct me if I'm wrong but I don't see
why we couldn't virtualize containers instead. Everybody thinks this means
slower performance but most of today's compilers are smart enough to bypass
the virtual tables. Let's consider the following:

template <typename T>
class list_base : public ...{ /* common operations */ ... };

template <typename T, typename Alloc>
class list : public list_base<T{ ... };
-Phil

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Aug 20 '08 #6
On Aug 20, 12:57*pm, "Phil Bouchard" <p...@fornux.comwrote:
"mlimber" <mlim...@gmail.comwrote in message

news:b5**********************************@e53g2000 hsa.googlegroups.com...
On Aug 20, 4:26 am, "Phil Bouchard" <p...@fornux.comwrote:

[...]
I still don't get it. Let's say you're designing std::vector, which
has an allocator template parameter. It doesn't matter if the user-
defined class or a smart pointer (as long as it has value semantics).
Given this code:
*class C { */...*/ };
*// ...
*std::vector<Cv1( 10 );
*std::vector< std::tr1::shared_ptr<C v2( 10 );
Under the hood, each of the latter two lines will use vector's
(default) allocator to grab memory for the 10 instances of the
contained type and then placement-new to construct the instances in
that memory. (Note that all the shared_ptr's pointees are null at this
point.) Why does the allocator care if it's making a C or a
shared_ptr<C>?
Cheers! --M

Indeed in that case it won't matter because the pools used to allocate nodes
from the container and to deallocate objects from the smart pointer are not
shared. *Sometimes it is in our favor to share to same pool used by the
container and the smart pointer. *For example shifted_ptr<uses this to
prevent cyclicism (still requires STL modifications).

Either we do it this way or we share the allocator across the container and
smart pointer so that the smart pointer uses deallocate(void *):

1)
std::vector<shifted_ptr<int>, shifted_allocator<shifted_ptr<int c1;

2)
std::vector<shifted_ptr<int, shifted_allocator<int,
shifted_allocator<shifted_ptr<int, shifted_allocator<int c2;

I don't even think option 2) is implementable.
I may just be dense, but I still don't see what you're getting at.
Can't you just use the deleter parameter to indicate special deletion?
Something like this (untested):

class C { /*...*/ };

template<class Alloc>
class MyDeleter
{
Alloc& m_alloc;

typedef typename Alloc::value_type T;

public:
MyDeleter( Alloc& alloc ) : m_alloc( alloc ) {}

// Might want a const T* version also
void operator()( T* const ptr )
{
m_alloc.destroy( ptr );
m_alloc.deallocate( ptr, sizeof(T) );
}
};

void Foo( MyAllocator<C>& alloc, const C& initVal )
{
typedef std::vector< std::tr1::shared_ptr<C VSPC;
VSPC v( 10 );
for( VSPC::iterator it=v.begin(); it != v.end(); ++it )
{
// Could hide these next lines in a factory function
C* const c = alloc.allocate( sizeof(C) );
alloc.construct( c, initVal );

it->reset( c, MyDeleter( m_alloc ) );
}
// ...
}

Now, when the vector "v" goes out of scope, the shared_ptrs use the
"alloc" object to deallocate their pointees.

Cheers! --M
Aug 20 '08 #7
mlimber wrote:
template<class Alloc>
class MyDeleter
{
Alloc& m_alloc;

typedef typename Alloc::value_type T;

public:
MyDeleter( Alloc& alloc ) : m_alloc( alloc ) {}

// Might want a const T* version also
void operator()( T* const ptr )
{
m_alloc.destroy( ptr );
m_alloc.deallocate( ptr, sizeof(T) );
}
};
Oops. This won't work as written because of the reference member and
the default copy constructor, but that's easy to fix and you get the
idea.

Cheers! --M
Aug 20 '08 #8

"mlimber" <ml*****@gmail.comwrote in message
news:2e**********************************@d77g2000 hsb.googlegroups.com...
On Aug 20, 12:57 pm, "Phil Bouchard" <p...@fornux.comwrote:
[...]
Either we do it this way or we share the allocator across the container
and
smart pointer so that the smart pointer uses deallocate(void *):

1)
std::vector<shifted_ptr<int>, shifted_allocator<shifted_ptr<int c1;

2)
std::vector<shifted_ptr<int, shifted_allocator<int,
shifted_allocator<shifted_ptr<int, shifted_allocator<int c2;

I don't even think option 2) is implementable.

I may just be dense, but I still don't see what you're getting at.
Can't you just use the deleter parameter to indicate special deletion?
Something like this (untested):

class C { /*...*/ };

template<class Alloc>
class MyDeleter
{
Alloc& m_alloc;

typedef typename Alloc::value_type T;

public:
MyDeleter( Alloc& alloc ) : m_alloc( alloc ) {}

// Might want a const T* version also
void operator()( T* const ptr )
{
m_alloc.destroy( ptr );
m_alloc.deallocate( ptr, sizeof(T) );
}
};

void Foo( MyAllocator<C>& alloc, const C& initVal )
{
typedef std::vector< std::tr1::shared_ptr<C VSPC;
VSPC v( 10 );
for( VSPC::iterator it=v.begin(); it != v.end(); ++it )
{
// Could hide these next lines in a factory function
C* const c = alloc.allocate( sizeof(C) );
alloc.construct( c, initVal );

it->reset( c, MyDeleter( m_alloc ) );
}
// ...
}

Now, when the vector "v" goes out of scope, the shared_ptrs use the
"alloc" object to deallocate their pointees.
What you are suggesting is very similar to option 2) I was anteriorly
explaining. In my case I was using the allocator passed in as a template
parameter as a deleter so that there is no need to repeatedly call the
overloaded constructor shared_ptr(T *, D *). I can't imagine calling this
special constructor for each node pointer inside a container in a flexible
way. If I forget calling it for one pointer the compiler will not report
any compilation error.
-Phil
Aug 21 '08 #9
On Aug 21, 8:40*am, "Phil Bouchard" <p...@fornux.comwrote:
"mlimber" <mlim...@gmail.comwrote in message

news:2e**********************************@d77g2000 hsb.googlegroups.com...
On Aug 20, 12:57 pm, "Phil Bouchard" <p...@fornux.comwrote:

[...]
Either we do it this way or we share the allocator across the container
and
smart pointer so that the smart pointer uses deallocate(void *):
1)
std::vector<shifted_ptr<int>, shifted_allocator<shifted_ptr<int c1;
2)
std::vector<shifted_ptr<int, shifted_allocator<int,
shifted_allocator<shifted_ptr<int, shifted_allocator<int c2;
I don't even think option 2) is implementable.
I may just be dense, but I still don't see what you're getting at.
Can't you just use the deleter parameter to indicate special deletion?
Something like this (untested):
* class C { /*...*/ };
* template<class Alloc>
* class MyDeleter
* {
* * Alloc& m_alloc;
* * typedef typename Alloc::value_type T;
* public:
* * MyDeleter( Alloc& alloc ) : m_alloc( alloc ) {}
* * // Might want a const T* version also
* * void operator()( T* const ptr )
* * {
* * * m_alloc.destroy( ptr );
* * * m_alloc.deallocate( ptr, sizeof(T) );
* * }
* };
* void Foo( MyAllocator<C>& alloc, const C& initVal )
* {
* * typedef std::vector< std::tr1::shared_ptr<C VSPC;
* * VSPC v( 10 );
* * for( VSPC::iterator it=v.begin(); it != v.end(); ++it )
* * {
* * * // Could hide these next lines in a factory function
* * * C* const c = alloc.allocate( sizeof(C) );
* * * alloc.construct( c, initVal );
* * * it->reset( c, MyDeleter( m_alloc ) );
* * }
* * // ...
* }
Now, when the vector "v" goes out of scope, the shared_ptrs use the
"alloc" object to deallocate their pointees.

What you are suggesting is very similar to option 2) I was anteriorly
explaining. *In my case I was using the allocator passed in as a template
parameter as a deleter so that there is no need to repeatedly call the
overloaded constructor shared_ptr(T *, D *). *I can't imagine calling this
special constructor for each node pointer inside a container in a flexible
way. *If I forget calling it for one pointer the compiler will not report
any compilation error.
You said your option 2 was not implementable (perhaps it isn't; my
attempt was a little different). Have I presented a working
implementation supported by the standard and the approved extensions
in TR1 that accomplishes your goal of not having a smart pointer
expose itself for the sake of custom allocators? If so, it seems to me
that no change in the standard libraries is necessary, and authors of
smart pointers just need to model their own smart pointer design on
the standard one (cf. Scott Meyers's explanation of custom deleters:
http://www.artima.com/cppsource/top_..._moments.html).

Moreover, use of custom allocators is rather rare in my experience,
but those who need them will need to be diligent in their use. Calling
an alternate constructor/reset function doesn't seem like a heavy
burden for that small number of advanced users, particularly when it
is combined with RAII techniques for proper destruction.

Compare also the discussion of memory pools in the FAQs:

http://www.parashift.com/c++-faq-lit...html#faq-11.14

Cheers! --M
Aug 21 '08 #10

"Phil Bouchard" <ph**@fornux.comwrote in message
news:g8**********@aioe.org...

[...]
template <typename T>
class list_base : public ...{ /* common operations */ ... };

template <typename T, typename Alloc>
class list : public list_base<T{ ... };
Where:
template <typename T>
virtual allocator_type list_base<T>::get_allocator() const = 0;

And, for example:
template <typename T, typename Alloc>
virtual allocator_type list<T, Alloc>::get_allocator() const
{
return allocator_type(*static_cast<const
_Node_Alloc_type*>(&this->_M_impl));
}
-Phil

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Aug 21 '08 #11

"mlimber" <ml*****@gmail.comwrote in message
news:57**********************************@l64g2000 hse.googlegroups.com...
any compilation error.
You said your option 2 was not implementable (perhaps it isn't; my
attempt was a little different). Have I presented a working
implementation supported by the standard and the approved extensions
in TR1 that accomplishes your goal of not having a smart pointer
expose itself for the sake of custom allocators? If so, it seems to me
that no change in the standard libraries is necessary, and authors of
smart pointers just need to model their own smart pointer design on
the standard one (cf. Scott Meyers's explanation of custom deleters:
http://www.artima.com/cppsource/top_..._moments.html).
No changes are required, I just want to make sure allocator do not become
virtual! I think there was a paper on this but I haven't followed up latest
clarifications.
Moreover, use of custom allocators is rather rare in my experience,
but those who need them will need to be diligent in their use. Calling
an alternate constructor/reset function doesn't seem like a heavy
burden for that small number of advanced users, particularly when it
is combined with RAII techniques for proper destruction.

Compare also the discussion of memory pools in the FAQs:

http://www.parashift.com/c++-faq-lit...html#faq-11.14
I will read those later... ;)
-Phil
Aug 22 '08 #12

"Phil Bouchard" <ph**@fornux.comwrote in message
news:g8**********@aioe.org...

[...]
Where:
template <typename T>
virtual allocator_type list_base<T>::get_allocator() const = 0;

And, for example:
template <typename T, typename Alloc>
virtual allocator_type list<T, Alloc>::get_allocator() const
{
return allocator_type(*static_cast<const
_Node_Alloc_type*>(&this->_M_impl));
}
Sorry here I meant protected functions should be virtual, not
get_allocator():

template <typename T>
class list_base : public ...
{
virtual _List_node<_Tp>* _M_get_node() = 0;
virtual void _M_put_node(_List_node<_Tp>* __p) = 0;
};

template <typename T, typename Alloc>
class list : public list_base<T>
{
protected:
_List_impl _M_impl;

virtual _List_node<_Tp>* _M_get_node()
{
return _M_impl._Node_Alloc_type::allocate(1);
}

virtual void _M_put_node(_List_node<_Tp>* __p)
{
_M_impl._Node_Alloc_type::deallocate(__p, 1);
}

public:
_Alloc get_allocator() const
{
return _Alloc(*static_cast<const
_Node_Alloc_type*>(&this->_M_impl));
}

...
};
-Phil

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Aug 22 '08 #13

"Phil Bouchard" <ph**@fornux.comwrote in message
news:g8**********@aioe.org...

[...]
No changes are required, I just want to make sure allocator do not become
virtual! I think there was a paper on this but I haven't followed up
latest clarifications.
[...]

Yeah that was n2387:
http://www.open-std.org/jtc1/sc22/wg...2007/n2387.pdf

This one needs to be canceled.
-Phil
Aug 23 '08 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Orjan Westin | last post by:
Hi, I have an interesting (read frustrating) problem. I'm writing a generic container class, which holds data as well as links to other instances of itself, like this: template<class T>...
2
by: Joshua Kolden | last post by:
STL allocators are templates so that when you write one you are obliged to make it work with any type. However, the Intel IPP library that we use has memory aligned allocators for each of 15...
7
by: Grahamo | last post by:
Hi, can anybody tell me where I can get the boiler plate code for std::allocator. I need to have my version of new and delete called and want to get reference code. My compilers headers are all...
3
by: Alex Vinokur | last post by:
Compiler GNU g++ version 3.4.4 (cygming special) Custom allocator for vector (see below) checks a return value of 'operator new'. If that value is NULL, the allocator "allocates" no memory....
0
by: joe | last post by:
I have created a custom allocator for a multiset, and I am having a problem it seems because while the allocator has memory available to be used which is returned, the objects are never constructed...
3
by: joe | last post by:
I have written a custom std allocator which follows the example in Stroustrup's book. I'm seeing a behavior I don't understand. My allocate method within the allocator looks like the...
9
by: OuaisBla | last post by:
Although STL container can't support object by reference as a template argument. To make thing worse, allocator can't support stack based allocation. So: std::deque<std::string const &> is...
3
by: Mike | last post by:
Hi, I have a simple "memPool' class that simply maintains a linked list of chunks from which allocation requests are made. The whole thing is deleted all at once upon destruction. So far, so...
16
by: PeterAPIIT | last post by:
Hello all C++ expert programmer, i have wrote partial general allocator for my container. After reading standard C++ library and code guru article, i have several questions. 1. Why...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.